implemented wait on a semaphore group and related semaphore handling
This commit is contained in:
parent
6711bc01fa
commit
ce72ffa193
@ -55,8 +55,9 @@ class Semaphore(Object)
|
||||
fireTimeNsec := 0,
|
||||
ioIndex := -1,
|
||||
ioHandle := nil,
|
||||
ioMask := 0,
|
||||
group := nil.
|
||||
ioMask := 0.
|
||||
|
||||
var(#get,#set) _group := nil.
|
||||
|
||||
method(#class) forMutualExclusion
|
||||
{
|
||||
@ -148,7 +149,7 @@ TODO: timed wait...
|
||||
}
|
||||
elsif (sem == zzz)
|
||||
{
|
||||
}
|
||||
}.
|
||||
}
|
||||
|
||||
============ CASE 2====================
|
||||
@ -225,8 +226,17 @@ method(#class,#abstract) xxx. => method(#class) xxx { self subclassResponsibilit
|
||||
|
||||
method initialize: arr
|
||||
{
|
||||
| i sem |
|
||||
self.size := arr size.
|
||||
self.semarr := arr.
|
||||
|
||||
i := 0.
|
||||
while (i < self.size)
|
||||
{
|
||||
sem := self.semarr at: i.
|
||||
sem _group: self.
|
||||
i := i + 1.
|
||||
}
|
||||
}
|
||||
|
||||
method(#primitive) wait.
|
||||
|
@ -473,6 +473,7 @@ static MOO_INLINE void chain_into_semaphore (moo_t* moo, moo_oop_process_t proc,
|
||||
MOO_ASSERT (moo, (moo_oop_t)proc->sem_wait.prev == moo->_nil);
|
||||
MOO_ASSERT (moo, (moo_oop_t)proc->sem_wait.next == moo->_nil);
|
||||
|
||||
/* a semaphore or a semaphore group must be given for process chaining */
|
||||
MOO_ASSERT (moo, MOO_CLASSOF(moo,sem) == moo->_semaphore ||
|
||||
MOO_CLASSOF(moo,sem) == moo->_semaphore_group);
|
||||
|
||||
@ -684,6 +685,7 @@ static void yield_process (moo_t* moo, moo_oop_process_t proc)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int async_signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
|
||||
{
|
||||
if (moo->sem_list_count >= SEM_LIST_MAX)
|
||||
@ -709,6 +711,7 @@ static int async_signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
|
||||
moo->sem_list_count++;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
|
||||
{
|
||||
@ -717,7 +720,7 @@ static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
|
||||
|
||||
if ((moo_oop_t)sem->group != moo->_nil)
|
||||
{
|
||||
/* the semaphore belongs to a group */
|
||||
/* the semaphore belongs to a semaphore group */
|
||||
moo_oop_semaphore_group_t semgrp;
|
||||
|
||||
semgrp = sem->group;
|
||||
@ -733,6 +736,17 @@ static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
|
||||
}
|
||||
}
|
||||
|
||||
/* if the semaphore belongs to a semaphore group, no process is waiting
|
||||
* on the semaphore group. however, a process may still be waiting on
|
||||
* the semaphore. If a process waits on a semaphore group and another
|
||||
* process wait on a semaphor that belongs to the semaphore group, the
|
||||
* process waiting on the group always wins.
|
||||
*
|
||||
* TODO: implement a fair scheduling policy. or do i simply have to disallow individual wait on a semaphore belonging to a group?
|
||||
*
|
||||
* if it doesn't belong to a sempahore group, i'm free from the ambiguity
|
||||
* issue.
|
||||
*/
|
||||
if ((moo_oop_t)sem->waiting.first == moo->_nil)
|
||||
{
|
||||
/* no process is waiting on this semaphore */
|
||||
@ -761,12 +775,22 @@ static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
|
||||
}
|
||||
}
|
||||
|
||||
static void await_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
|
||||
static int await_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
|
||||
{
|
||||
/* TODO: support timeout */
|
||||
moo_oop_process_t proc;
|
||||
moo_ooi_t count;
|
||||
|
||||
#if 0
|
||||
/* TODO: do i have to disallow?? */
|
||||
if ((moo_oop_t)sem->group != moo->_nil)
|
||||
{
|
||||
/* disallow a semaphore in a semaphore group to be waited on */
|
||||
moo_seterrnum (moo, MOO_EPERM);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
count = MOO_OOP_TO_SMOOI(sem->count);
|
||||
if (count > 0)
|
||||
{
|
||||
@ -791,6 +815,8 @@ static void await_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
|
||||
|
||||
MOO_ASSERT (moo, moo->processor->active != proc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static moo_oop_t await_semaphore_group (moo_t* moo, moo_oop_semaphore_group_t semgrp)
|
||||
@ -840,7 +866,7 @@ static moo_oop_t await_semaphore_group (moo_t* moo, moo_oop_semaphore_group_t se
|
||||
if (MOO_OOP_TO_SMOOI(sem->io_index) >= 0) moo->sem_io_wait_count++;
|
||||
}
|
||||
#else
|
||||
/* link the suspended process to the semaphore's process list */
|
||||
/* link the suspended process to the semaphore group's process list */
|
||||
chain_into_semaphore (moo, proc, (moo_oop_semaphore_t)semgrp);
|
||||
MOO_ASSERT (moo, semgrp->waiting.last == proc);
|
||||
/*if (MOO_OOP_TO_SMOOI(sem->io_index) >= 0) moo->sem_io_wait_count++;*/
|
||||
@ -2468,7 +2494,11 @@ static moo_pfrc_t pf_semaphore_wait (moo_t* moo, moo_ooi_t nargs)
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
await_semaphore (moo, (moo_oop_semaphore_t)rcv);
|
||||
if (await_semaphore (moo, (moo_oop_semaphore_t)rcv) <= -1)
|
||||
{
|
||||
MOO_STACK_SETRETTOERRNUM (moo, nargs);
|
||||
return -1;
|
||||
}
|
||||
|
||||
MOO_STACK_SETRETTORCV (moo, nargs);
|
||||
return MOO_PF_SUCCESS;
|
||||
|
Loading…
Reference in New Issue
Block a user