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 /* if the semaphore belongs to a semaphore group and the control reaches
* here, no process is waiting on the semaphore group. however, a process * 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 * 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. * 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? * 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 */ /* no process is waiting on this semaphore */
count = MOO_OOP_TO_SMOOI(sem->count); 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++; count++;
sem->count = MOO_SMOOI_TO_OOP(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 */ /* no process has been resumed */
return (moo_oop_process_t)moo->_nil; 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) if ((moo_oop_t)semgrp != moo->_nil && count == 0)
{ {
int sems_idx;
/* TODO: if i disallow individual wait on a semaphore in a group, /* TODO: if i disallow individual wait on a semaphore in a group,
* this membership manipulation is redundant */ * this membership manipulation is redundant */
MOO_DELETE_FROM_OOP_LIST (moo, &semgrp->sigsems, sem, grm); MOO_DELETE_FROM_OOP_LIST (moo, &semgrp->sems[MOO_SEMAPHORE_GROUP_SEMS_SIG], sem, grm);
MOO_APPEND_TO_OOP_LIST (moo, &semgrp->sems, moo_oop_semaphore_t, 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 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) 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 */ /* wait for one of semaphores in the group to be signaled */
moo_oop_process_t proc; 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)); 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) if ((moo_oop_t)sem != moo->_nil)
{ {
moo_ooi_t count; moo_ooi_t count;
int sems_idx;
count = MOO_OOP_TO_SMOOI(sem->count); count = MOO_OOP_TO_SMOOI(sem->count);
MOO_ASSERT (moo, count > 0); MOO_ASSERT (moo, count > 0);
count--; count--;
sem->count = MOO_SMOOI_TO_OOP(count); sem->count = MOO_SMOOI_TO_OOP(count);
MOO_DELETE_FROM_OOP_LIST (moo, &semgrp->sigsems, sem, grm); MOO_DELETE_FROM_OOP_LIST (moo, &semgrp->sems[MOO_SEMAPHORE_GROUP_SEMS_SIG], sem, grm);
if (count > 0) 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);
/* 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);
}
return (moo_oop_t)sem; 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_t)sem->group == moo->_nil)
{ {
if (MOO_OOP_TO_SMOOI(sem->count) > 0) 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->sigsems, moo_oop_semaphore_t, sem, grm); MOO_APPEND_TO_OOP_LIST (moo, &rcv->sems[sems_idx], moo_oop_semaphore_t, sem, grm);
}
else
{
MOO_APPEND_TO_OOP_LIST (moo, &rcv->sems, moo_oop_semaphore_t, sem, grm);
}
sem->group = rcv; sem->group = rcv;
MOO_STACK_SETRETTORCV (moo, nargs); 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 else
{ {
/* the semaphore belongs to a group already */ /* 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); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EPERM);
} }
return MOO_PF_SUCCESS; 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); 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)); 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 */ int sems_idx;
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EPERM); 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 else
{ {
if (MOO_OOP_TO_SMOOI(sem->count) > 0) /* it doesn't belong to a group or belongs to a different group */
{ MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EPERM);
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);
} }
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;

View File

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