enhanced primitive methods and operations on a semaphore group

This commit is contained in:
hyunghwan.chung 2017-10-08 18:13:10 +00:00
parent 643d70f474
commit 016b7c2dac
2 changed files with 43 additions and 53 deletions

View File

@ -769,7 +769,7 @@ static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
/* if the semaphore belongs to a semaphore group and the control reaches
* here, 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
* group and another process wait on a semaphore 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?
@ -780,17 +780,18 @@ static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
{
/* no process is waiting on this semaphore */
count = MOO_OOP_TO_SMOOI(sem->count);
MOO_ASSERT (moo, count >= 0);
if (count == 0 && (moo_oop_t)semgrp != moo->_nil)
{
/* move the semaphore from the unsignaled list to the signaled list
* if the semaphore count has changed from 0 to 1 and it belongs a group. */
MOO_DELETE_FROM_OOP_LIST (moo, &semgrp->sems, sem, grm);
MOO_APPEND_TO_OOP_LIST (moo, &semgrp->sigsems, moo_oop_semaphore_t, sem, grm);
}
count++;
sem->count = MOO_SMOOI_TO_OOP(count);
MOO_ASSERT (moo, count >= 1);
if (count == 1 && (moo_oop_t)semgrp != moo->_nil)
{
/* move the semaphore from the unsignaled list to the signaled list
* if the semaphore count has changed from 0 to 1 in a group */
MOO_DELETE_FROM_OOP_LIST (moo, &semgrp->sems[MOO_SEMAPHORE_GROUP_SEMS_UNSIG], sem, grm);
MOO_APPEND_TO_OOP_LIST (moo, &semgrp->sems[MOO_SEMAPHORE_GROUP_SEMS_SIG], moo_oop_semaphore_t, sem, grm);
}
/* no process has been resumed */
return (moo_oop_process_t)moo->_nil;
}
@ -838,10 +839,12 @@ static MOO_INLINE void await_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
if ((moo_oop_t)semgrp != moo->_nil && count == 0)
{
int sems_idx;
/* TODO: if i disallow individual wait on a semaphore in a group,
* this membership manipulation is redundant */
MOO_DELETE_FROM_OOP_LIST (moo, &semgrp->sigsems, sem, grm);
MOO_APPEND_TO_OOP_LIST (moo, &semgrp->sems, moo_oop_semaphore_t, sem, grm);
MOO_DELETE_FROM_OOP_LIST (moo, &semgrp->sems[MOO_SEMAPHORE_GROUP_SEMS_SIG], sem, grm);
sems_idx = count > 0? MOO_SEMAPHORE_GROUP_SEMS_SIG: MOO_SEMAPHORE_GROUP_SEMS_UNSIG;
MOO_APPEND_TO_OOP_LIST (moo, &semgrp->sems[sems_idx], moo_oop_semaphore_t, sem, grm);
}
}
else
@ -869,7 +872,6 @@ static MOO_INLINE void await_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
static MOO_INLINE moo_oop_t await_semaphore_group (moo_t* moo, moo_oop_semaphore_group_t semgrp)
{
/* TODO: support timeout and wait all */
/* wait for one of semaphores in the group to be signaled */
moo_oop_process_t proc;
@ -877,27 +879,20 @@ static MOO_INLINE moo_oop_t await_semaphore_group (moo_t* moo, moo_oop_semaphore
MOO_ASSERT (moo, moo_iskindof(moo, (moo_oop_t)semgrp, moo->_semaphore_group));
sem = semgrp->sigsems.first;
sem = semgrp->sems[MOO_SEMAPHORE_GROUP_SEMS_SIG].first;
if ((moo_oop_t)sem != moo->_nil)
{
moo_ooi_t count;
int sems_idx;
count = MOO_OOP_TO_SMOOI(sem->count);
MOO_ASSERT (moo, count > 0);
count--;
sem->count = MOO_SMOOI_TO_OOP(count);
MOO_DELETE_FROM_OOP_LIST (moo, &semgrp->sigsems, sem, grm);
if (count > 0)
{
/* move the item to the back of signaled semaphore list */
MOO_APPEND_TO_OOP_LIST (moo, &semgrp->sigsems, moo_oop_semaphore_t, sem, grm);
}
else
{
/* move the semaphore to the unsigned semaphore list */
MOO_APPEND_TO_OOP_LIST (moo, &semgrp->sems, moo_oop_semaphore_t, sem, grm);
}
MOO_DELETE_FROM_OOP_LIST (moo, &semgrp->sems[MOO_SEMAPHORE_GROUP_SEMS_SIG], sem, grm);
sems_idx = count > 0? MOO_SEMAPHORE_GROUP_SEMS_SIG: MOO_SEMAPHORE_GROUP_SEMS_UNSIG;
MOO_APPEND_TO_OOP_LIST (moo, &semgrp->sems[sems_idx], moo_oop_semaphore_t, sem, grm);
return (moo_oop_t)sem;
}
@ -2576,20 +2571,21 @@ static moo_pfrc_t pf_semaphore_group_add_semaphore (moo_t* moo, moo_ooi_t nargs)
if ((moo_oop_t)sem->group == moo->_nil)
{
if (MOO_OOP_TO_SMOOI(sem->count) > 0)
{
MOO_APPEND_TO_OOP_LIST (moo, &rcv->sigsems, moo_oop_semaphore_t, sem, grm);
}
else
{
MOO_APPEND_TO_OOP_LIST (moo, &rcv->sems, moo_oop_semaphore_t, sem, grm);
}
int sems_idx;
sems_idx = MOO_OOP_TO_SMOOI(sem->count) > 0? MOO_SEMAPHORE_GROUP_SEMS_SIG: MOO_SEMAPHORE_GROUP_SEMS_UNSIG;
MOO_APPEND_TO_OOP_LIST (moo, &rcv->sems[sems_idx], moo_oop_semaphore_t, sem, grm);
sem->group = rcv;
MOO_STACK_SETRETTORCV (moo, nargs);
}
else if (sem->group == rcv)
{
/* do nothing. don't change the group of the semaphore */
MOO_STACK_SETRETTORCV (moo, nargs);
}
else
{
/* the semaphore belongs to a group already */
/* TODO: is it better to move this semaphore to the new group? */
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EPERM);
}
return MOO_PF_SUCCESS;
@ -2606,24 +2602,21 @@ static moo_pfrc_t pf_semaphore_group_remove_semaphore (moo_t* moo, moo_ooi_t nar
sem = (moo_oop_semaphore_t)MOO_STACK_GETARG (moo, nargs, 0);
MOO_PF_CHECK_ARGS (moo, nargs, moo_iskindof(moo, (moo_oop_t)sem, moo->_semaphore));
if ((moo_oop_t)sem->group == moo->_nil)
if (sem->group == rcv)
{
/* it doesn't belong to a group */
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EPERM);
int sems_idx;
sems_idx = MOO_OOP_TO_SMOOI(sem->count) > 0? MOO_SEMAPHORE_GROUP_SEMS_SIG: MOO_SEMAPHORE_GROUP_SEMS_UNSIG;
MOO_DELETE_FROM_OOP_LIST (moo, &rcv->sems[sems_idx], sem, grm);
sem->grm.prev = (moo_oop_semaphore_t)moo->_nil;
sem->grm.next = (moo_oop_semaphore_t)moo->_nil;
sem->group = (moo_oop_semaphore_group_t)moo->_nil;
MOO_STACK_SETRETTORCV (moo, nargs);
}
else
{
if (MOO_OOP_TO_SMOOI(sem->count) > 0)
{
MOO_DELETE_FROM_OOP_LIST (moo, &rcv->sigsems, sem, grm);
}
else
{
MOO_DELETE_FROM_OOP_LIST (moo, &rcv->sems, sem, grm);
}
sem->group = (moo_oop_semaphore_group_t)moo->_nil;
MOO_STACK_SETRETTORCV (moo, nargs);
/* it doesn't belong to a group or belongs to a different group */
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EPERM);
}
return MOO_PF_SUCCESS;

View File

@ -823,6 +823,9 @@ struct moo_semaphore_t
} grm; /* group membership chain */
};
#define MOO_SEMAPHORE_GROUP_SEMS_UNSIG 0
#define MOO_SEMAPHORE_GROUP_SEMS_SIG 1
struct moo_semaphore_group_t
{
MOO_OBJ_HEADER;
@ -840,13 +843,7 @@ struct moo_semaphore_group_t
{
moo_oop_semaphore_t first;
moo_oop_semaphore_t last;
} sems;
struct
{
moo_oop_semaphore_t first;
moo_oop_semaphore_t last;
} sigsems;
} sems[2]; /* sems[0] - unsignaled semaphores, sems[1] - signaled semaphores */
};
#define MOO_PROCESS_SCHEDULER_NAMED_INSTVARS 9