Uses a free list of semaphore slots for faster creation now.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4225 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+130
-80
@@ -34,19 +34,32 @@
|
|||||||
|
|
||||||
struct sem_entry {
|
struct sem_entry {
|
||||||
sem_id id;
|
sem_id id;
|
||||||
|
spinlock lock; // protects only the id field when unused
|
||||||
|
union {
|
||||||
|
// when slot in use
|
||||||
|
struct {
|
||||||
int count;
|
int count;
|
||||||
struct thread_queue q;
|
struct thread_queue q;
|
||||||
char *name;
|
char *name;
|
||||||
spinlock lock;
|
|
||||||
team_id owner; // if set to -1, means owned by a port
|
team_id owner; // if set to -1, means owned by a port
|
||||||
|
} used;
|
||||||
|
|
||||||
|
// when slot unused
|
||||||
|
struct {
|
||||||
|
sem_id next_id;
|
||||||
|
struct sem_entry *next;
|
||||||
|
} unused;
|
||||||
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Todo: Compute based on the amount of available memory.
|
||||||
#define MAX_SEMS 4096
|
#define MAX_SEMS 4096
|
||||||
|
|
||||||
static struct sem_entry *gSems = NULL;
|
static struct sem_entry *gSems = NULL;
|
||||||
static region_id gSemRegion = 0;
|
static region_id gSemRegion = 0;
|
||||||
static bool gSemsActive = false;
|
static bool gSemsActive = false;
|
||||||
static sem_id gNextSemID = 0;
|
static struct sem_entry *gFreeSemsHead = NULL;
|
||||||
|
static struct sem_entry *gFreeSemsTail = NULL;
|
||||||
|
|
||||||
static spinlock sem_spinlock = 0;
|
static spinlock sem_spinlock = 0;
|
||||||
#define GRAB_SEM_LIST_LOCK() acquire_spinlock(&sem_spinlock)
|
#define GRAB_SEM_LIST_LOCK() acquire_spinlock(&sem_spinlock)
|
||||||
@@ -70,7 +83,8 @@ dump_sem_list(int argc, char **argv)
|
|||||||
|
|
||||||
for (i = 0; i < MAX_SEMS; i++) {
|
for (i = 0; i < MAX_SEMS; i++) {
|
||||||
if (gSems[i].id >= 0)
|
if (gSems[i].id >= 0)
|
||||||
dprintf("%p\tid: 0x%lx\t\tname: '%s'\n", &gSems[i], gSems[i].id, gSems[i].name);
|
dprintf("%p\tid: 0x%lx\t\tname: '%s'\n", &gSems[i], gSems[i].id,
|
||||||
|
gSems[i].u.used.name);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -80,10 +94,17 @@ static void
|
|||||||
dump_sem(struct sem_entry *sem)
|
dump_sem(struct sem_entry *sem)
|
||||||
{
|
{
|
||||||
dprintf("SEM: %p\n", sem);
|
dprintf("SEM: %p\n", sem);
|
||||||
dprintf("name: '%s'\n", sem->name);
|
dprintf("id: %ld\n", sem->id);
|
||||||
dprintf("owner: 0x%lx\n", sem->owner);
|
if (sem->id >= 0) {
|
||||||
dprintf("count: 0x%x\n", sem->count);
|
dprintf("name: '%s'\n", sem->u.used.name);
|
||||||
dprintf("queue: head %p tail %p\n", sem->q.head, sem->q.tail);
|
dprintf("owner: 0x%lx\n", sem->u.used.owner);
|
||||||
|
dprintf("count: 0x%x\n", sem->u.used.count);
|
||||||
|
dprintf("queue: head %p tail %p\n", sem->u.used.q.head,
|
||||||
|
sem->u.used.q.tail);
|
||||||
|
} else {
|
||||||
|
dprintf("next: %p\n", sem->u.unused.next);
|
||||||
|
dprintf("next_id: %ld\n", sem->u.unused.next_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -118,8 +139,8 @@ dump_sem_info(int argc, char **argv)
|
|||||||
|
|
||||||
// walk through the sem list, trying to match name
|
// walk through the sem list, trying to match name
|
||||||
for (i = 0; i < MAX_SEMS; i++) {
|
for (i = 0; i < MAX_SEMS; i++) {
|
||||||
if (gSems[i].name != NULL
|
if (gSems[i].u.used.name != NULL
|
||||||
&& strcmp(argv[1], gSems[i].name) == 0) {
|
&& strcmp(argv[1], gSems[i].u.used.name) == 0) {
|
||||||
dump_sem(&gSems[i]);
|
dump_sem(&gSems[i]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -127,6 +148,34 @@ dump_sem_info(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \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)
|
||||||
|
{
|
||||||
|
struct sem_entry *sem = gSems + slot;
|
||||||
|
// set next_id to the next possible value; for sanity check the current ID
|
||||||
|
if (nextID < 0)
|
||||||
|
sem->u.unused.next_id = slot;
|
||||||
|
else
|
||||||
|
sem->u.unused.next_id = nextID;
|
||||||
|
// append the entry to the list
|
||||||
|
if (gFreeSemsTail)
|
||||||
|
gFreeSemsTail->u.unused.next = sem;
|
||||||
|
else
|
||||||
|
gFreeSemsHead = sem;
|
||||||
|
gFreeSemsTail = sem;
|
||||||
|
sem->u.unused.next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
sem_init(kernel_args *ka)
|
sem_init(kernel_args *ka)
|
||||||
@@ -143,8 +192,10 @@ sem_init(kernel_args *ka)
|
|||||||
panic("unable to allocate semaphore table!\n");
|
panic("unable to allocate semaphore table!\n");
|
||||||
|
|
||||||
memset(gSems, 0, sizeof(struct sem_entry) * MAX_SEMS);
|
memset(gSems, 0, sizeof(struct sem_entry) * MAX_SEMS);
|
||||||
for (i = 0; i < MAX_SEMS; i++)
|
for (i = 0; i < MAX_SEMS; i++) {
|
||||||
gSems[i].id = -1;
|
gSems[i].id = -1;
|
||||||
|
free_sem_slot(i, i);
|
||||||
|
}
|
||||||
|
|
||||||
// add debugger commands
|
// add debugger commands
|
||||||
add_debugger_command("sems", &dump_sem_list, "Dump a list of all active semaphores");
|
add_debugger_command("sems", &dump_sem_list, "Dump a list of all active semaphores");
|
||||||
@@ -169,7 +220,7 @@ sem_init(kernel_args *ka)
|
|||||||
sem_id
|
sem_id
|
||||||
create_sem_etc(int32 count, const char *name, team_id owner)
|
create_sem_etc(int32 count, const char *name, team_id owner)
|
||||||
{
|
{
|
||||||
int i;
|
struct sem_entry *sem = NULL;
|
||||||
int state;
|
int state;
|
||||||
sem_id retval = B_NO_MORE_SEMS;
|
sem_id retval = B_NO_MORE_SEMS;
|
||||||
char *temp_name;
|
char *temp_name;
|
||||||
@@ -191,47 +242,31 @@ create_sem_etc(int32 count, const char *name, team_id owner)
|
|||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_SEM_LIST_LOCK();
|
GRAB_SEM_LIST_LOCK();
|
||||||
|
|
||||||
// find the first empty spot
|
// get the first slot from the free list
|
||||||
for (i = 0; i < MAX_SEMS; i++) {
|
sem = gFreeSemsHead;
|
||||||
if (gSems[i].id == -1) {
|
if (sem) {
|
||||||
// adjust the sem ID so that: sem ID % MAX_SEMS == slot
|
// remove it from the free list
|
||||||
if (i >= gNextSemID % MAX_SEMS)
|
gFreeSemsHead = sem->u.unused.next;
|
||||||
gNextSemID += i - gNextSemID % MAX_SEMS;
|
if (!gFreeSemsHead)
|
||||||
else
|
gFreeSemsTail = NULL;
|
||||||
gNextSemID += MAX_SEMS - (gNextSemID % MAX_SEMS - i);
|
// init the slot
|
||||||
gSems[i].id = gNextSemID;
|
GRAB_SEM_LOCK(*sem);
|
||||||
|
sem->id = sem->u.unused.next_id;
|
||||||
// increment next free sem ID, check for overflow
|
sem->u.used.count = count;
|
||||||
if (++gNextSemID < 0)
|
sem->u.used.q.tail = NULL;
|
||||||
gNextSemID = 0;
|
sem->u.used.q.head = NULL;
|
||||||
|
sem->u.used.name = temp_name;
|
||||||
// Set the owner while the sem list lock is hold, or else it
|
sem->u.used.owner = owner;
|
||||||
// might get lost if we have a sem_delete_owned_sems() running
|
RELEASE_SEM_LOCK(*sem);
|
||||||
// (although this should be impossible (if create_sem_etc() is
|
retval = sem->id;
|
||||||
// just properly, I just feel better with it).
|
|
||||||
gSems[i].owner = owner;
|
|
||||||
|
|
||||||
gSems[i].lock = 0;
|
|
||||||
GRAB_SEM_LOCK(gSems[i]);
|
|
||||||
RELEASE_SEM_LIST_LOCK();
|
|
||||||
|
|
||||||
gSems[i].q.tail = NULL;
|
|
||||||
gSems[i].q.head = NULL;
|
|
||||||
gSems[i].count = count;
|
|
||||||
gSems[i].name = temp_name;
|
|
||||||
retval = gSems[i].id;
|
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[i]);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RELEASE_SEM_LIST_LOCK();
|
RELEASE_SEM_LIST_LOCK();
|
||||||
free(temp_name);
|
|
||||||
|
|
||||||
out:
|
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
if (!sem)
|
||||||
|
free(temp_name);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,7 +316,7 @@ delete_sem_etc(sem_id id, status_t return_code, bool interrupted)
|
|||||||
release_queue.head = release_queue.tail = NULL;
|
release_queue.head = release_queue.tail = NULL;
|
||||||
|
|
||||||
// free any threads waiting for this semaphore
|
// free any threads waiting for this semaphore
|
||||||
while ((t = thread_dequeue(&gSems[slot].q)) != NULL) {
|
while ((t = thread_dequeue(&gSems[slot].u.used.q)) != NULL) {
|
||||||
t->state = B_THREAD_READY;
|
t->state = B_THREAD_READY;
|
||||||
t->sem_errcode = interrupted ? B_INTERRUPTED : B_BAD_SEM_ID;
|
t->sem_errcode = interrupted ? B_INTERRUPTED : B_BAD_SEM_ID;
|
||||||
t->sem_deleted_retcode = return_code;
|
t->sem_deleted_retcode = return_code;
|
||||||
@@ -291,11 +326,16 @@ delete_sem_etc(sem_id id, status_t return_code, bool interrupted)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gSems[slot].id = -1;
|
gSems[slot].id = -1;
|
||||||
old_name = gSems[slot].name;
|
old_name = gSems[slot].u.used.name;
|
||||||
gSems[slot].name = NULL;
|
gSems[slot].u.used.name = NULL;
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(gSems[slot]);
|
||||||
|
|
||||||
|
// append slot to the free list
|
||||||
|
GRAB_SEM_LIST_LOCK();
|
||||||
|
free_sem_slot(slot, id + MAX_SEMS);
|
||||||
|
RELEASE_SEM_LIST_LOCK();
|
||||||
|
|
||||||
if (released_threads > 0) {
|
if (released_threads > 0) {
|
||||||
GRAB_THREAD_LOCK();
|
GRAB_THREAD_LOCK();
|
||||||
while ((t = thread_dequeue(&release_queue)) != NULL) {
|
while ((t = thread_dequeue(&release_queue)) != NULL) {
|
||||||
@@ -392,24 +432,26 @@ acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gSems[slot].count - count < 0 && (flags & B_TIMEOUT) != 0 && timeout <= 0) {
|
if (gSems[slot].u.used.count - count < 0 && (flags & B_TIMEOUT) != 0
|
||||||
|
&& timeout <= 0) {
|
||||||
// immediate timeout
|
// immediate timeout
|
||||||
status = B_WOULD_BLOCK;
|
status = B_WOULD_BLOCK;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((gSems[slot].count -= count) < 0) {
|
if ((gSems[slot].u.used.count -= count) < 0) {
|
||||||
// we need to block
|
// we need to block
|
||||||
struct thread *t = thread_get_current_thread();
|
struct thread *t = thread_get_current_thread();
|
||||||
timer timeout_timer; // stick it on the stack, since we may be blocking here
|
timer timeout_timer; // stick it on the stack, since we may be blocking here
|
||||||
struct sem_timeout_args args;
|
struct sem_timeout_args args;
|
||||||
|
|
||||||
TRACE_BLOCK(("acquire_sem_etc(id = %ld): block name = %s, thread = %p, name = %s\n", id, gSems[slot].name, t, t->name));
|
TRACE_BLOCK(("acquire_sem_etc(id = %ld): block name = %s, thread = %p,"
|
||||||
|
" name = %s\n", id, gSems[slot].u.used.name, t, t->name));
|
||||||
|
|
||||||
// do a quick check to see if the thread has any pending signals
|
// do a quick check to see if the thread has any pending signals
|
||||||
// this should catch most of the cases where the thread had a signal
|
// this should catch most of the cases where the thread had a signal
|
||||||
if ((flags & B_CAN_INTERRUPT) && t->sig_pending) {
|
if ((flags & B_CAN_INTERRUPT) && t->sig_pending) {
|
||||||
gSems[slot].count += count;
|
gSems[slot].u.used.count += count;
|
||||||
status = B_INTERRUPTED;
|
status = B_INTERRUPTED;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -418,10 +460,11 @@ acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout)
|
|||||||
t->sem_flags = flags;
|
t->sem_flags = flags;
|
||||||
t->sem_blocking = id;
|
t->sem_blocking = id;
|
||||||
t->sem_acquire_count = count;
|
t->sem_acquire_count = count;
|
||||||
t->sem_count = min(-gSems[slot].count, count); // store the count we need to restore upon release
|
t->sem_count = min(-gSems[slot].u.used.count, count);
|
||||||
|
// store the count we need to restore upon release
|
||||||
t->sem_deleted_retcode = 0;
|
t->sem_deleted_retcode = 0;
|
||||||
t->sem_errcode = B_NO_ERROR;
|
t->sem_errcode = B_NO_ERROR;
|
||||||
thread_enqueue(t, &gSems[slot].q);
|
thread_enqueue(t, &gSems[slot].u.used.q);
|
||||||
|
|
||||||
if ((flags & (B_TIMEOUT | B_ABSOLUTE_TIMEOUT)) != 0) {
|
if ((flags & (B_TIMEOUT | B_ABSOLUTE_TIMEOUT)) != 0) {
|
||||||
TRACE(("sem_acquire_etc: setting timeout sem for %d %d usecs, semid %d, tid %d\n",
|
TRACE(("sem_acquire_etc: setting timeout sem for %d %d usecs, semid %d, tid %d\n",
|
||||||
@@ -473,7 +516,9 @@ acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout)
|
|||||||
|
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
TRACE_BLOCK(("acquire_sem_etc(id = %ld): exit block name = %s, thread = %p (%s)\n", id, gSems[slot].name, t, t->name));
|
TRACE_BLOCK(("acquire_sem_etc(id = %ld): exit block name = %s, "
|
||||||
|
"thread = %p (%s)\n", id, gSems[slot].u.used.name, t,
|
||||||
|
t->name));
|
||||||
return t->sem_errcode;
|
return t->sem_errcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,14 +570,14 @@ release_sem_etc(sem_id id, int32 count, uint32 flags)
|
|||||||
|
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
int delta = count;
|
int delta = count;
|
||||||
if (gSems[slot].count < 0) {
|
if (gSems[slot].u.used.count < 0) {
|
||||||
struct thread *t = thread_lookat_queue(&gSems[slot].q);
|
struct thread *t = thread_lookat_queue(&gSems[slot].u.used.q);
|
||||||
|
|
||||||
delta = min(count, t->sem_count);
|
delta = min(count, t->sem_count);
|
||||||
t->sem_count -= delta;
|
t->sem_count -= delta;
|
||||||
if (t->sem_count <= 0) {
|
if (t->sem_count <= 0) {
|
||||||
// release this thread
|
// release this thread
|
||||||
t = thread_dequeue(&gSems[slot].q);
|
t = thread_dequeue(&gSems[slot].u.used.q);
|
||||||
thread_enqueue(t, &release_queue);
|
thread_enqueue(t, &release_queue);
|
||||||
t->state = B_THREAD_READY;
|
t->state = B_THREAD_READY;
|
||||||
released_threads++;
|
released_threads++;
|
||||||
@@ -541,7 +586,7 @@ release_sem_etc(sem_id id, int32 count, uint32 flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gSems[slot].count += delta;
|
gSems[slot].u.used.count += delta;
|
||||||
count -= delta;
|
count -= delta;
|
||||||
}
|
}
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(gSems[slot]);
|
||||||
@@ -599,7 +644,7 @@ get_sem_count(sem_id id, int32 *thread_count)
|
|||||||
return B_BAD_SEM_ID;
|
return B_BAD_SEM_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
*thread_count = gSems[slot].count;
|
*thread_count = gSems[slot].u.used.count;
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(gSems[slot]);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
@@ -640,10 +685,11 @@ _get_sem_info(sem_id id, struct sem_info *info, size_t sz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
info->sem = gSems[slot].id;
|
info->sem = gSems[slot].id;
|
||||||
info->team = gSems[slot].owner;
|
info->team = gSems[slot].u.used.owner;
|
||||||
strncpy(info->name, gSems[slot].name, SYS_MAX_OS_NAME_LEN-1);
|
strncpy(info->name, gSems[slot].u.used.name, SYS_MAX_OS_NAME_LEN-1);
|
||||||
info->count = gSems[slot].count;
|
info->count = gSems[slot].u.used.count;
|
||||||
info->latest_holder = gSems[slot].q.head->id; // XXX not sure if this is correct
|
info->latest_holder = gSems[slot].u.used.q.head->id;
|
||||||
|
// XXX not sure if this is correct
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(gSems[slot]);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
@@ -688,15 +734,18 @@ _get_next_sem_info(team_id team, int32 *cookie, struct sem_info *info, size_t sz
|
|||||||
GRAB_SEM_LIST_LOCK();
|
GRAB_SEM_LIST_LOCK();
|
||||||
|
|
||||||
while (slot < MAX_SEMS) {
|
while (slot < MAX_SEMS) {
|
||||||
if (gSems[slot].id != -1 && gSems[slot].owner == team) {
|
if (gSems[slot].id != -1 && gSems[slot].u.used.owner == team) {
|
||||||
GRAB_SEM_LOCK(gSems[slot]);
|
GRAB_SEM_LOCK(gSems[slot]);
|
||||||
if (gSems[slot].id != -1 && gSems[slot].owner == team) {
|
if (gSems[slot].id != -1 && gSems[slot].u.used.owner == team) {
|
||||||
// found one!
|
// found one!
|
||||||
info->sem = gSems[slot].id;
|
info->sem = gSems[slot].id;
|
||||||
info->team = gSems[slot].owner;
|
info->team = gSems[slot].u.used.owner;
|
||||||
strncpy(info->name, gSems[slot].name, SYS_MAX_OS_NAME_LEN-1);
|
strncpy(info->name, gSems[slot].u.used.name,
|
||||||
info->count = gSems[slot].count;
|
SYS_MAX_OS_NAME_LEN-1);
|
||||||
info->latest_holder = gSems[slot].q.head->id; // XXX not sure if this is the latest holder, or the next holder...
|
info->count = gSems[slot].u.used.count;
|
||||||
|
info->latest_holder = gSems[slot].u.used.q.head->id;
|
||||||
|
// XXX not sure if this is the latest holder, or the next
|
||||||
|
// holder...
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(gSems[slot]);
|
||||||
slot++;
|
slot++;
|
||||||
@@ -749,7 +798,7 @@ set_sem_owner(sem_id id, team_id team)
|
|||||||
// Todo: this is a small race condition: the team ID could already
|
// Todo: this is a small race condition: the team ID could already
|
||||||
// be invalid at this point - we would lose one semaphore slot in
|
// be invalid at this point - we would lose one semaphore slot in
|
||||||
// this case!
|
// this case!
|
||||||
gSems[slot].owner = team;
|
gSems[slot].u.used.owner = team;
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(gSems[slot]);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
@@ -808,25 +857,26 @@ remove_thread_from_sem(struct thread *t, struct sem_entry *sem, struct thread_qu
|
|||||||
struct thread *t1;
|
struct thread *t1;
|
||||||
|
|
||||||
// remove the thread from the queue and place it in the supplied queue
|
// remove the thread from the queue and place it in the supplied queue
|
||||||
t1 = thread_dequeue_id(&sem->q, t->id);
|
t1 = thread_dequeue_id(&sem->u.used.q, t->id);
|
||||||
if (t != t1)
|
if (t != t1)
|
||||||
return ERR_NOT_FOUND;
|
return ERR_NOT_FOUND;
|
||||||
sem->count += t->sem_acquire_count;
|
sem->u.used.count += t->sem_acquire_count;
|
||||||
t->state = t->next_state = B_THREAD_READY;
|
t->state = t->next_state = B_THREAD_READY;
|
||||||
t->sem_errcode = sem_errcode;
|
t->sem_errcode = sem_errcode;
|
||||||
thread_enqueue(t, queue);
|
thread_enqueue(t, queue);
|
||||||
|
|
||||||
// now see if more threads need to be woken up
|
// now see if more threads need to be woken up
|
||||||
while (sem->count > 0 && (t1 = thread_lookat_queue(&sem->q))) {
|
while (sem->u.used.count > 0
|
||||||
int delta = min(t->sem_count, sem->count);
|
&& (t1 = thread_lookat_queue(&sem->u.used.q))) {
|
||||||
|
int delta = min(t->sem_count, sem->u.used.count);
|
||||||
|
|
||||||
t->sem_count -= delta;
|
t->sem_count -= delta;
|
||||||
if (t->sem_count <= 0) {
|
if (t->sem_count <= 0) {
|
||||||
t = thread_dequeue(&sem->q);
|
t = thread_dequeue(&sem->u.used.q);
|
||||||
t->state = t->next_state = B_THREAD_READY;
|
t->state = t->next_state = B_THREAD_READY;
|
||||||
thread_enqueue(t, queue);
|
thread_enqueue(t, queue);
|
||||||
}
|
}
|
||||||
sem->count -= delta;
|
sem->u.used.count -= delta;
|
||||||
}
|
}
|
||||||
return B_NO_ERROR;
|
return B_NO_ERROR;
|
||||||
}
|
}
|
||||||
@@ -850,7 +900,7 @@ sem_delete_owned_sems(team_id owner)
|
|||||||
GRAB_SEM_LIST_LOCK();
|
GRAB_SEM_LIST_LOCK();
|
||||||
|
|
||||||
for (i = 0; i < MAX_SEMS; i++) {
|
for (i = 0; i < MAX_SEMS; i++) {
|
||||||
if (gSems[i].id != -1 && gSems[i].owner == owner) {
|
if (gSems[i].id != -1 && gSems[i].u.used.owner == owner) {
|
||||||
sem_id id = gSems[i].id;
|
sem_id id = gSems[i].id;
|
||||||
|
|
||||||
RELEASE_SEM_LIST_LOCK();
|
RELEASE_SEM_LIST_LOCK();
|
||||||
|
|||||||
Reference in New Issue
Block a user