enhanced primitive methods and operations on a semaphore group
This commit is contained in:
parent
643d70f474
commit
016b7c2dac
@ -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;
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user