implemented wait on a semaphore group and related semaphore handling

This commit is contained in:
hyunghwan.chung 2017-09-21 14:22:36 +00:00
parent 6711bc01fa
commit ce72ffa193
2 changed files with 47 additions and 7 deletions

View File

@ -55,8 +55,9 @@ class Semaphore(Object)
fireTimeNsec := 0, fireTimeNsec := 0,
ioIndex := -1, ioIndex := -1,
ioHandle := nil, ioHandle := nil,
ioMask := 0, ioMask := 0.
group := nil.
var(#get,#set) _group := nil.
method(#class) forMutualExclusion method(#class) forMutualExclusion
{ {
@ -148,7 +149,7 @@ TODO: timed wait...
} }
elsif (sem == zzz) elsif (sem == zzz)
{ {
} }.
} }
============ CASE 2==================== ============ CASE 2====================
@ -225,8 +226,17 @@ method(#class,#abstract) xxx. => method(#class) xxx { self subclassResponsibilit
method initialize: arr method initialize: arr
{ {
| i sem |
self.size := arr size. self.size := arr size.
self.semarr := arr. self.semarr := arr.
i := 0.
while (i < self.size)
{
sem := self.semarr at: i.
sem _group: self.
i := i + 1.
}
} }
method(#primitive) wait. method(#primitive) wait.

View File

@ -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.prev == moo->_nil);
MOO_ASSERT (moo, (moo_oop_t)proc->sem_wait.next == 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_ASSERT (moo, MOO_CLASSOF(moo,sem) == moo->_semaphore ||
MOO_CLASSOF(moo,sem) == moo->_semaphore_group); 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) static int async_signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
{ {
if (moo->sem_list_count >= SEM_LIST_MAX) 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++; moo->sem_list_count++;
return 0; return 0;
} }
#endif
static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem) 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) 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; moo_oop_semaphore_group_t semgrp;
semgrp = sem->group; 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) if ((moo_oop_t)sem->waiting.first == moo->_nil)
{ {
/* no process is waiting on this semaphore */ /* 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 */ /* TODO: support timeout */
moo_oop_process_t proc; moo_oop_process_t proc;
moo_ooi_t count; 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); count = MOO_OOP_TO_SMOOI(sem->count);
if (count > 0) 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); 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) 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++; if (MOO_OOP_TO_SMOOI(sem->io_index) >= 0) moo->sem_io_wait_count++;
} }
#else #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); chain_into_semaphore (moo, proc, (moo_oop_semaphore_t)semgrp);
MOO_ASSERT (moo, semgrp->waiting.last == proc); MOO_ASSERT (moo, semgrp->waiting.last == proc);
/*if (MOO_OOP_TO_SMOOI(sem->io_index) >= 0) moo->sem_io_wait_count++;*/ /*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; 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); MOO_STACK_SETRETTORCV (moo, nargs);
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;