Got rid of gSemRegion as it is never really used.
Renamed all static global variables to have the 's' prefix. acquire_sem_etc() now fails if B_RELATIVE_TIMEOUT and B_ABSOLUTE_TIMEOUT are both set. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9854 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+105
-100
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2002-2004, The Haiku Team. All rights reserved.
|
** Copyright 2002-2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
** Distributed under the terms of the Haiku License.
|
** Distributed under the terms of the Haiku License.
|
||||||
**
|
**
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
@@ -55,11 +55,10 @@ struct sem_entry {
|
|||||||
static int32 sMaxSems = 4096;
|
static int32 sMaxSems = 4096;
|
||||||
static int32 sUsedSems = 0;
|
static int32 sUsedSems = 0;
|
||||||
|
|
||||||
static struct sem_entry *gSems = NULL;
|
static struct sem_entry *sSems = NULL;
|
||||||
static region_id gSemRegion = 0;
|
static bool sSemsActive = false;
|
||||||
static bool gSemsActive = false;
|
static struct sem_entry *sFreeSemsHead = NULL;
|
||||||
static struct sem_entry *gFreeSemsHead = NULL;
|
static struct sem_entry *sFreeSemsTail = 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)
|
||||||
@@ -83,9 +82,9 @@ dump_sem_list(int argc, char **argv)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < sMaxSems; i++) {
|
for (i = 0; i < sMaxSems; i++) {
|
||||||
if (gSems[i].id >= 0)
|
if (sSems[i].id >= 0)
|
||||||
dprintf("%p\tid: 0x%lx\t\tname: '%s'\n", &gSems[i], gSems[i].id,
|
dprintf("%p\tid: 0x%lx\t\tname: '%s'\n", &sSems[i], sSems[i].id,
|
||||||
gSems[i].u.used.name);
|
sSems[i].u.used.name);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -129,20 +128,20 @@ dump_sem_info(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
unsigned slot = num % sMaxSems;
|
unsigned slot = num % sMaxSems;
|
||||||
if (gSems[slot].id != (int)num) {
|
if (sSems[slot].id != (int)num) {
|
||||||
dprintf("sem 0x%lx doesn't exist!\n", num);
|
dprintf("sem 0x%lx doesn't exist!\n", num);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dump_sem(&gSems[slot]);
|
dump_sem(&sSems[slot]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk through the sem list, trying to match name
|
// walk through the sem list, trying to match name
|
||||||
for (i = 0; i < sMaxSems; i++) {
|
for (i = 0; i < sMaxSems; i++) {
|
||||||
if (gSems[i].u.used.name != NULL
|
if (sSems[i].u.used.name != NULL
|
||||||
&& strcmp(argv[1], gSems[i].u.used.name) == 0) {
|
&& strcmp(argv[1], sSems[i].u.used.name) == 0) {
|
||||||
dump_sem(&gSems[i]);
|
dump_sem(&sSems[i]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,18 +162,18 @@ dump_sem_info(int argc, char **argv)
|
|||||||
static void
|
static void
|
||||||
free_sem_slot(int slot, sem_id nextID)
|
free_sem_slot(int slot, sem_id nextID)
|
||||||
{
|
{
|
||||||
struct sem_entry *sem = gSems + slot;
|
struct sem_entry *sem = sSems + slot;
|
||||||
// set next_id to the next possible value; for sanity check the current ID
|
// set next_id to the next possible value; for sanity check the current ID
|
||||||
if (nextID < 0)
|
if (nextID < 0)
|
||||||
sem->u.unused.next_id = slot;
|
sem->u.unused.next_id = slot;
|
||||||
else
|
else
|
||||||
sem->u.unused.next_id = nextID;
|
sem->u.unused.next_id = nextID;
|
||||||
// append the entry to the list
|
// append the entry to the list
|
||||||
if (gFreeSemsTail)
|
if (sFreeSemsTail)
|
||||||
gFreeSemsTail->u.unused.next = sem;
|
sFreeSemsTail->u.unused.next = sem;
|
||||||
else
|
else
|
||||||
gFreeSemsHead = sem;
|
sFreeSemsHead = sem;
|
||||||
gFreeSemsTail = sem;
|
sFreeSemsTail = sem;
|
||||||
sem->u.unused.next = NULL;
|
sem->u.unused.next = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,19 +181,20 @@ free_sem_slot(int slot, sem_id nextID)
|
|||||||
status_t
|
status_t
|
||||||
sem_init(kernel_args *ka)
|
sem_init(kernel_args *ka)
|
||||||
{
|
{
|
||||||
|
area_id area;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
TRACE(("sem_init: entry\n"));
|
TRACE(("sem_init: entry\n"));
|
||||||
|
|
||||||
// create and initialize semaphore table
|
// create and initialize semaphore table
|
||||||
gSemRegion = create_area("sem_table", (void **)&gSems, B_ANY_KERNEL_ADDRESS,
|
area = create_area("sem_table", (void **)&sSems, B_ANY_KERNEL_ADDRESS,
|
||||||
sizeof(struct sem_entry) * sMaxSems, B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
sizeof(struct sem_entry) * sMaxSems, B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||||
if (gSemRegion < 0)
|
if (area < 0)
|
||||||
panic("unable to allocate semaphore table!\n");
|
panic("unable to allocate semaphore table!\n");
|
||||||
|
|
||||||
memset(gSems, 0, sizeof(struct sem_entry) * sMaxSems);
|
memset(sSems, 0, sizeof(struct sem_entry) * sMaxSems);
|
||||||
for (i = 0; i < sMaxSems; i++) {
|
for (i = 0; i < sMaxSems; i++) {
|
||||||
gSems[i].id = -1;
|
sSems[i].id = -1;
|
||||||
free_sem_slot(i, i);
|
free_sem_slot(i, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ sem_init(kernel_args *ka)
|
|||||||
|
|
||||||
TRACE(("sem_init: exit\n"));
|
TRACE(("sem_init: exit\n"));
|
||||||
|
|
||||||
gSemsActive = true;
|
sSemsActive = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -227,7 +227,7 @@ create_sem_etc(int32 count, const char *name, team_id owner)
|
|||||||
char *tempName;
|
char *tempName;
|
||||||
size_t nameLength;
|
size_t nameLength;
|
||||||
|
|
||||||
if (gSemsActive == false || sUsedSems == sMaxSems)
|
if (sSemsActive == false || sUsedSems == sMaxSems)
|
||||||
return B_NO_MORE_SEMS;
|
return B_NO_MORE_SEMS;
|
||||||
|
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
@@ -244,12 +244,12 @@ create_sem_etc(int32 count, const char *name, team_id owner)
|
|||||||
GRAB_SEM_LIST_LOCK();
|
GRAB_SEM_LIST_LOCK();
|
||||||
|
|
||||||
// get the first slot from the free list
|
// get the first slot from the free list
|
||||||
sem = gFreeSemsHead;
|
sem = sFreeSemsHead;
|
||||||
if (sem) {
|
if (sem) {
|
||||||
// remove it from the free list
|
// remove it from the free list
|
||||||
gFreeSemsHead = sem->u.unused.next;
|
sFreeSemsHead = sem->u.unused.next;
|
||||||
if (!gFreeSemsHead)
|
if (!sFreeSemsHead)
|
||||||
gFreeSemsTail = NULL;
|
sFreeSemsTail = NULL;
|
||||||
// init the slot
|
// init the slot
|
||||||
GRAB_SEM_LOCK(*sem);
|
GRAB_SEM_LOCK(*sem);
|
||||||
sem->id = sem->u.unused.next_id;
|
sem->id = sem->u.unused.next_id;
|
||||||
@@ -291,7 +291,7 @@ delete_sem(sem_id id)
|
|||||||
char *old_name;
|
char *old_name;
|
||||||
struct thread_queue release_queue;
|
struct thread_queue release_queue;
|
||||||
|
|
||||||
if (gSemsActive == false)
|
if (sSemsActive == false)
|
||||||
return B_NO_MORE_SEMS;
|
return B_NO_MORE_SEMS;
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
return B_BAD_SEM_ID;
|
return B_BAD_SEM_ID;
|
||||||
@@ -299,10 +299,10 @@ delete_sem(sem_id id)
|
|||||||
slot = id % sMaxSems;
|
slot = id % sMaxSems;
|
||||||
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_SEM_LOCK(gSems[slot]);
|
GRAB_SEM_LOCK(sSems[slot]);
|
||||||
|
|
||||||
if (gSems[slot].id != id) {
|
if (sSems[slot].id != id) {
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
TRACE(("delete_sem: invalid sem_id %ld\n", id));
|
TRACE(("delete_sem: invalid sem_id %ld\n", id));
|
||||||
return B_BAD_SEM_ID;
|
return B_BAD_SEM_ID;
|
||||||
@@ -312,7 +312,7 @@ delete_sem(sem_id id)
|
|||||||
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].u.used.q)) != NULL) {
|
while ((t = thread_dequeue(&sSems[slot].u.used.q)) != NULL) {
|
||||||
t->state = B_THREAD_READY;
|
t->state = B_THREAD_READY;
|
||||||
t->sem.acquire_status = B_BAD_SEM_ID;
|
t->sem.acquire_status = B_BAD_SEM_ID;
|
||||||
t->sem.count = 0;
|
t->sem.count = 0;
|
||||||
@@ -320,11 +320,11 @@ delete_sem(sem_id id)
|
|||||||
released_threads++;
|
released_threads++;
|
||||||
}
|
}
|
||||||
|
|
||||||
gSems[slot].id = -1;
|
sSems[slot].id = -1;
|
||||||
old_name = gSems[slot].u.used.name;
|
old_name = sSems[slot].u.used.name;
|
||||||
gSems[slot].u.used.name = NULL;
|
sSems[slot].u.used.name = NULL;
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
|
|
||||||
// append slot to the free list
|
// append slot to the free list
|
||||||
GRAB_SEM_LIST_LOCK();
|
GRAB_SEM_LIST_LOCK();
|
||||||
@@ -366,20 +366,20 @@ sem_timeout(timer *data)
|
|||||||
slot = args->blocked_sem_id % sMaxSems;
|
slot = args->blocked_sem_id % sMaxSems;
|
||||||
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_SEM_LOCK(gSems[slot]);
|
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));
|
TRACE(("sem_timeout: called on 0x%x sem %ld, tid %ld\n", data, args->blocked_sem_id, args->blocked_thread));
|
||||||
|
|
||||||
if (gSems[slot].id != args->blocked_sem_id) {
|
if (sSems[slot].id != args->blocked_sem_id) {
|
||||||
// this thread was not waiting on this semaphore
|
// 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",
|
panic("sem_timeout: thid %ld was trying to wait on sem %ld which doesn't exist!\n",
|
||||||
args->blocked_thread, args->blocked_sem_id);
|
args->blocked_thread, args->blocked_sem_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
wakeup_queue.head = wakeup_queue.tail = NULL;
|
wakeup_queue.head = wakeup_queue.tail = NULL;
|
||||||
remove_thread_from_sem(t, &gSems[slot], &wakeup_queue, B_TIMED_OUT);
|
remove_thread_from_sem(t, &sSems[slot], &wakeup_queue, B_TIMED_OUT);
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
|
|
||||||
GRAB_THREAD_LOCK();
|
GRAB_THREAD_LOCK();
|
||||||
// put the threads in the run q here to make sure we dont deadlock in sem_interrupt_thread
|
// put the threads in the run q here to make sure we dont deadlock in sem_interrupt_thread
|
||||||
@@ -408,7 +408,7 @@ acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout)
|
|||||||
int state;
|
int state;
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
|
|
||||||
if (gSemsActive == false)
|
if (sSemsActive == false)
|
||||||
return B_NO_MORE_SEMS;
|
return B_NO_MORE_SEMS;
|
||||||
|
|
||||||
if (!kernel_startup && !are_interrupts_enabled())
|
if (!kernel_startup && !are_interrupts_enabled())
|
||||||
@@ -416,38 +416,40 @@ acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout)
|
|||||||
|
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
return B_BAD_SEM_ID;
|
return B_BAD_SEM_ID;
|
||||||
if (count <= 0)
|
if (count <= 0
|
||||||
|
|| (flags & (B_RELATIVE_TIMEOUT | B_ABSOLUTE_TIMEOUT)) == (B_RELATIVE_TIMEOUT | B_ABSOLUTE_TIMEOUT)) {
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_SEM_LOCK(gSems[slot]);
|
GRAB_SEM_LOCK(sSems[slot]);
|
||||||
|
|
||||||
if (gSems[slot].id != id) {
|
if (sSems[slot].id != id) {
|
||||||
TRACE(("acquire_sem_etc: bad sem_id %ld\n", id));
|
TRACE(("acquire_sem_etc: bad sem_id %ld\n", id));
|
||||||
status = B_BAD_SEM_ID;
|
status = B_BAD_SEM_ID;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gSems[slot].u.used.count - count < 0 && (flags & B_TIMEOUT) != 0
|
if (sSems[slot].u.used.count - count < 0 && (flags & B_TIMEOUT) != 0
|
||||||
&& timeout <= 0) {
|
&& timeout <= 0) {
|
||||||
// immediate timeout
|
// immediate timeout
|
||||||
status = B_WOULD_BLOCK;
|
status = B_WOULD_BLOCK;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((gSems[slot].u.used.count -= count) < 0) {
|
if ((sSems[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,"
|
TRACE_BLOCK(("acquire_sem_etc(id = %ld): block name = %s, thread = %p,"
|
||||||
" name = %s\n", id, gSems[slot].u.used.name, t, t->name));
|
" name = %s\n", id, sSems[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].u.used.count += count;
|
sSems[slot].u.used.count += count;
|
||||||
status = B_INTERRUPTED;
|
status = B_INTERRUPTED;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -456,10 +458,10 @@ 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].u.used.count, count);
|
t->sem.count = min(-sSems[slot].u.used.count, count);
|
||||||
// store the count we need to restore upon release
|
// store the count we need to restore upon release
|
||||||
t->sem.acquire_status = B_NO_ERROR;
|
t->sem.acquire_status = B_NO_ERROR;
|
||||||
thread_enqueue(t, &gSems[slot].u.used.q);
|
thread_enqueue(t, &sSems[slot].u.used.q);
|
||||||
|
|
||||||
if ((flags & (B_RELATIVE_TIMEOUT | B_ABSOLUTE_TIMEOUT)) != 0) {
|
if ((flags & (B_RELATIVE_TIMEOUT | B_ABSOLUTE_TIMEOUT)) != 0) {
|
||||||
TRACE(("sem_acquire_etc: setting timeout sem for %Ld usecs, semid %d, tid %d\n",
|
TRACE(("sem_acquire_etc: setting timeout sem for %Ld usecs, semid %d, tid %d\n",
|
||||||
@@ -477,7 +479,7 @@ acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout)
|
|||||||
B_ONE_SHOT_RELATIVE_TIMER : B_ONE_SHOT_ABSOLUTE_TIMER);
|
B_ONE_SHOT_RELATIVE_TIMER : B_ONE_SHOT_ABSOLUTE_TIMER);
|
||||||
}
|
}
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
GRAB_THREAD_LOCK();
|
GRAB_THREAD_LOCK();
|
||||||
// check again to see if a signal is pending.
|
// check again to see if a signal is pending.
|
||||||
// it may have been delivered while setting up the sem, though it's pretty unlikely
|
// it may have been delivered while setting up the sem, though it's pretty unlikely
|
||||||
@@ -488,11 +490,11 @@ acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout)
|
|||||||
// here, since the threadlock is held. The previous check would have found most
|
// here, since the threadlock is held. The previous check would have found most
|
||||||
// instances, but there was a race, so we have to handle it. It'll be more messy...
|
// instances, but there was a race, so we have to handle it. It'll be more messy...
|
||||||
wakeup_queue.head = wakeup_queue.tail = NULL;
|
wakeup_queue.head = wakeup_queue.tail = NULL;
|
||||||
GRAB_SEM_LOCK(gSems[slot]);
|
GRAB_SEM_LOCK(sSems[slot]);
|
||||||
if (gSems[slot].id == id) {
|
if (sSems[slot].id == id) {
|
||||||
remove_thread_from_sem(t, &gSems[slot], &wakeup_queue, EINTR);
|
remove_thread_from_sem(t, &sSems[slot], &wakeup_queue, EINTR);
|
||||||
}
|
}
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
while ((t = thread_dequeue(&wakeup_queue)) != NULL) {
|
while ((t = thread_dequeue(&wakeup_queue)) != NULL) {
|
||||||
scheduler_enqueue_in_run_queue(t);
|
scheduler_enqueue_in_run_queue(t);
|
||||||
}
|
}
|
||||||
@@ -512,13 +514,13 @@ 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, "
|
TRACE_BLOCK(("acquire_sem_etc(id = %ld): exit block name = %s, "
|
||||||
"thread = %p (%s)\n", id, gSems[slot].u.used.name, t,
|
"thread = %p (%s)\n", id, sSems[slot].u.used.name, t,
|
||||||
t->name));
|
t->name));
|
||||||
return t->sem.acquire_status;
|
return t->sem.acquire_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
err:
|
err:
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -540,7 +542,7 @@ release_sem_etc(sem_id id, int32 count, uint32 flags)
|
|||||||
cpu_status state;
|
cpu_status state;
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
|
|
||||||
if (gSemsActive == false)
|
if (sSemsActive == false)
|
||||||
return B_NO_MORE_SEMS;
|
return B_NO_MORE_SEMS;
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
return B_BAD_SEM_ID;
|
return B_BAD_SEM_ID;
|
||||||
@@ -548,9 +550,9 @@ release_sem_etc(sem_id id, int32 count, uint32 flags)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_SEM_LOCK(gSems[slot]);
|
GRAB_SEM_LOCK(sSems[slot]);
|
||||||
|
|
||||||
if (gSems[slot].id != id) {
|
if (sSems[slot].id != id) {
|
||||||
TRACE(("sem_release_etc: invalid sem_id %ld\n", id));
|
TRACE(("sem_release_etc: invalid sem_id %ld\n", id));
|
||||||
status = B_BAD_SEM_ID;
|
status = B_BAD_SEM_ID;
|
||||||
goto err;
|
goto err;
|
||||||
@@ -563,7 +565,7 @@ release_sem_etc(sem_id id, int32 count, uint32 flags)
|
|||||||
releaseQueue.head = releaseQueue.tail = NULL;
|
releaseQueue.head = releaseQueue.tail = NULL;
|
||||||
|
|
||||||
if (flags & B_RELEASE_ALL) {
|
if (flags & B_RELEASE_ALL) {
|
||||||
count = -gSems[slot].u.used.count;
|
count = -sSems[slot].u.used.count;
|
||||||
|
|
||||||
// is there anything to do for us at all?
|
// is there anything to do for us at all?
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
@@ -572,14 +574,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].u.used.count < 0) {
|
if (sSems[slot].u.used.count < 0) {
|
||||||
struct thread *thread = thread_lookat_queue(&gSems[slot].u.used.q);
|
struct thread *thread = thread_lookat_queue(&sSems[slot].u.used.q);
|
||||||
|
|
||||||
delta = min(count, thread->sem.count);
|
delta = min(count, thread->sem.count);
|
||||||
thread->sem.count -= delta;
|
thread->sem.count -= delta;
|
||||||
if (thread->sem.count <= 0) {
|
if (thread->sem.count <= 0) {
|
||||||
// release this thread
|
// release this thread
|
||||||
thread = thread_dequeue(&gSems[slot].u.used.q);
|
thread = thread_dequeue(&sSems[slot].u.used.q);
|
||||||
thread_enqueue(thread, &releaseQueue);
|
thread_enqueue(thread, &releaseQueue);
|
||||||
thread->state = B_THREAD_READY;
|
thread->state = B_THREAD_READY;
|
||||||
thread->sem.count = 0;
|
thread->sem.count = 0;
|
||||||
@@ -587,10 +589,10 @@ release_sem_etc(sem_id id, int32 count, uint32 flags)
|
|||||||
} else if (flags & B_RELEASE_IF_WAITING_ONLY)
|
} else if (flags & B_RELEASE_IF_WAITING_ONLY)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
gSems[slot].u.used.count += delta;
|
sSems[slot].u.used.count += delta;
|
||||||
count -= delta;
|
count -= delta;
|
||||||
}
|
}
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
|
|
||||||
// pull off any items in the release queue and put them in the run queue
|
// pull off any items in the release queue and put them in the run queue
|
||||||
if (releaseQueue.head != NULL) {
|
if (releaseQueue.head != NULL) {
|
||||||
@@ -614,7 +616,7 @@ release_sem_etc(sem_id id, int32 count, uint32 flags)
|
|||||||
goto outnolock;
|
goto outnolock;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
outnolock:
|
outnolock:
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
@@ -628,7 +630,7 @@ get_sem_count(sem_id id, int32 *thread_count)
|
|||||||
int slot;
|
int slot;
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
if (gSemsActive == false)
|
if (sSemsActive == false)
|
||||||
return B_NO_MORE_SEMS;
|
return B_NO_MORE_SEMS;
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
return B_BAD_SEM_ID;
|
return B_BAD_SEM_ID;
|
||||||
@@ -638,18 +640,18 @@ get_sem_count(sem_id id, int32 *thread_count)
|
|||||||
slot = id % sMaxSems;
|
slot = id % sMaxSems;
|
||||||
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_SEM_LOCK(gSems[slot]);
|
GRAB_SEM_LOCK(sSems[slot]);
|
||||||
|
|
||||||
if (gSems[slot].id != id) {
|
if (sSems[slot].id != id) {
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
TRACE(("sem_get_count: invalid sem_id %ld\n", id));
|
TRACE(("sem_get_count: invalid sem_id %ld\n", id));
|
||||||
return B_BAD_SEM_ID;
|
return B_BAD_SEM_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
*thread_count = gSems[slot].u.used.count;
|
*thread_count = sSems[slot].u.used.count;
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
return B_NO_ERROR;
|
return B_NO_ERROR;
|
||||||
@@ -691,7 +693,7 @@ _get_sem_info(sem_id id, struct sem_info *info, size_t size)
|
|||||||
int state;
|
int state;
|
||||||
int slot;
|
int slot;
|
||||||
|
|
||||||
if (!gSemsActive)
|
if (!sSemsActive)
|
||||||
return B_NO_MORE_SEMS;
|
return B_NO_MORE_SEMS;
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
return B_BAD_SEM_ID;
|
return B_BAD_SEM_ID;
|
||||||
@@ -701,15 +703,15 @@ _get_sem_info(sem_id id, struct sem_info *info, size_t size)
|
|||||||
slot = id % sMaxSems;
|
slot = id % sMaxSems;
|
||||||
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_SEM_LOCK(gSems[slot]);
|
GRAB_SEM_LOCK(sSems[slot]);
|
||||||
|
|
||||||
if (gSems[slot].id != id) {
|
if (sSems[slot].id != id) {
|
||||||
status = B_BAD_SEM_ID;
|
status = B_BAD_SEM_ID;
|
||||||
TRACE(("get_sem_info: invalid sem_id %ld\n", id));
|
TRACE(("get_sem_info: invalid sem_id %ld\n", id));
|
||||||
} else
|
} else
|
||||||
fill_sem_info(&gSems[slot], info, size);
|
fill_sem_info(&sSems[slot], info, size);
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -729,14 +731,14 @@ _get_next_sem_info(team_id team, int32 *_cookie, struct sem_info *info, size_t s
|
|||||||
int slot;
|
int slot;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
if (!gSemsActive)
|
if (!sSemsActive)
|
||||||
return B_NO_MORE_SEMS;
|
return B_NO_MORE_SEMS;
|
||||||
if (_cookie == NULL || info == NULL || size != sizeof(sem_info))
|
if (_cookie == NULL || info == NULL || size != sizeof(sem_info))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
if (team == B_CURRENT_TEAM)
|
if (team == B_CURRENT_TEAM)
|
||||||
team = team_get_current_team_id();
|
team = team_get_current_team_id();
|
||||||
/* prevents gSems[].owner == -1 >= means owned by a port */
|
/* prevents sSems[].owner == -1 >= means owned by a port */
|
||||||
if (team < 0 || !team_is_valid(team))
|
if (team < 0 || !team_is_valid(team))
|
||||||
return B_BAD_TEAM_ID;
|
return B_BAD_TEAM_ID;
|
||||||
|
|
||||||
@@ -748,18 +750,18 @@ _get_next_sem_info(team_id team, int32 *_cookie, struct sem_info *info, size_t s
|
|||||||
GRAB_SEM_LIST_LOCK();
|
GRAB_SEM_LIST_LOCK();
|
||||||
|
|
||||||
while (slot < sMaxSems) {
|
while (slot < sMaxSems) {
|
||||||
if (gSems[slot].id != -1 && gSems[slot].u.used.owner == team) {
|
if (sSems[slot].id != -1 && sSems[slot].u.used.owner == team) {
|
||||||
GRAB_SEM_LOCK(gSems[slot]);
|
GRAB_SEM_LOCK(sSems[slot]);
|
||||||
if (gSems[slot].id != -1 && gSems[slot].u.used.owner == team) {
|
if (sSems[slot].id != -1 && sSems[slot].u.used.owner == team) {
|
||||||
// found one!
|
// found one!
|
||||||
fill_sem_info(&gSems[slot], info, size);
|
fill_sem_info(&sSems[slot], info, size);
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
slot++;
|
slot++;
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
}
|
}
|
||||||
slot++;
|
slot++;
|
||||||
}
|
}
|
||||||
@@ -780,7 +782,7 @@ set_sem_owner(sem_id id, team_id team)
|
|||||||
int state;
|
int state;
|
||||||
int slot;
|
int slot;
|
||||||
|
|
||||||
if (gSemsActive == false)
|
if (sSemsActive == false)
|
||||||
return B_NO_MORE_SEMS;
|
return B_NO_MORE_SEMS;
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
return B_BAD_SEM_ID;
|
return B_BAD_SEM_ID;
|
||||||
@@ -790,10 +792,10 @@ set_sem_owner(sem_id id, team_id team)
|
|||||||
slot = id % sMaxSems;
|
slot = id % sMaxSems;
|
||||||
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_SEM_LOCK(gSems[slot]);
|
GRAB_SEM_LOCK(sSems[slot]);
|
||||||
|
|
||||||
if (gSems[slot].id != id) {
|
if (sSems[slot].id != id) {
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
TRACE(("set_sem_owner: invalid sem_id %ld\n", id));
|
TRACE(("set_sem_owner: invalid sem_id %ld\n", id));
|
||||||
return B_BAD_SEM_ID;
|
return B_BAD_SEM_ID;
|
||||||
@@ -804,9 +806,9 @@ set_sem_owner(sem_id id, team_id team)
|
|||||||
// this case!
|
// this case!
|
||||||
// The only safe way to do this is to prevent either team (the new
|
// The only safe way to do this is to prevent either team (the new
|
||||||
// or the old owner) from dying until we leave the spinlock.
|
// or the old owner) from dying until we leave the spinlock.
|
||||||
gSems[slot].u.used.owner = team;
|
sSems[slot].u.used.owner = team;
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
return B_NO_ERROR;
|
return B_NO_ERROR;
|
||||||
@@ -833,17 +835,17 @@ sem_interrupt_thread(struct thread *t)
|
|||||||
|
|
||||||
slot = t->sem.blocking % sMaxSems;
|
slot = t->sem.blocking % sMaxSems;
|
||||||
|
|
||||||
GRAB_SEM_LOCK(gSems[slot]);
|
GRAB_SEM_LOCK(sSems[slot]);
|
||||||
|
|
||||||
if (gSems[slot].id != t->sem.blocking) {
|
if (sSems[slot].id != t->sem.blocking) {
|
||||||
panic("sem_interrupt_thread: thread 0x%lx sez it's blocking on sem 0x%lx, but that sem doesn't exist!\n", t->id, t->sem.blocking);
|
panic("sem_interrupt_thread: thread 0x%lx sez it's blocking on sem 0x%lx, but that sem doesn't exist!\n", t->id, t->sem.blocking);
|
||||||
}
|
}
|
||||||
|
|
||||||
wakeup_queue.head = wakeup_queue.tail = NULL;
|
wakeup_queue.head = wakeup_queue.tail = NULL;
|
||||||
if (remove_thread_from_sem(t, &gSems[slot], &wakeup_queue, EINTR) != B_OK)
|
if (remove_thread_from_sem(t, &sSems[slot], &wakeup_queue, EINTR) != B_OK)
|
||||||
panic("sem_interrupt_thread: thread 0x%lx not found in sem 0x%lx's wait queue\n", t->id, t->sem.blocking);
|
panic("sem_interrupt_thread: thread 0x%lx not found in sem 0x%lx's wait queue\n", t->id, t->sem.blocking);
|
||||||
|
|
||||||
RELEASE_SEM_LOCK(gSems[slot]);
|
RELEASE_SEM_LOCK(sSems[slot]);
|
||||||
|
|
||||||
while ((t = thread_dequeue(&wakeup_queue)) != NULL) {
|
while ((t = thread_dequeue(&wakeup_queue)) != NULL) {
|
||||||
scheduler_enqueue_in_run_queue(t);
|
scheduler_enqueue_in_run_queue(t);
|
||||||
@@ -902,6 +904,9 @@ sem_delete_owned_sems(team_id owner)
|
|||||||
int i;
|
int i;
|
||||||
int count = 0;
|
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)
|
if (owner < 0)
|
||||||
return B_BAD_TEAM_ID;
|
return B_BAD_TEAM_ID;
|
||||||
|
|
||||||
@@ -909,8 +914,8 @@ sem_delete_owned_sems(team_id owner)
|
|||||||
GRAB_SEM_LIST_LOCK();
|
GRAB_SEM_LIST_LOCK();
|
||||||
|
|
||||||
for (i = 0; i < sMaxSems; i++) {
|
for (i = 0; i < sMaxSems; i++) {
|
||||||
if (gSems[i].id != -1 && gSems[i].u.used.owner == owner) {
|
if (sSems[i].id != -1 && sSems[i].u.used.owner == owner) {
|
||||||
sem_id id = gSems[i].id;
|
sem_id id = sSems[i].id;
|
||||||
|
|
||||||
RELEASE_SEM_LIST_LOCK();
|
RELEASE_SEM_LIST_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|||||||
Reference in New Issue
Block a user