changed to support a pair of semaphores on a single handle for input and output respectively

This commit is contained in:
hyunghwan.chung
2017-12-24 17:36:20 +00:00
parent f27856fa72
commit 3d0bcf970e
18 changed files with 960 additions and 207 deletions

View File

@ -1,5 +1,7 @@
AUTOMAKE_OPTIONS = nostdinc
AM_CFLAGS = $(PTHREAD_CFLAGS)
CPPFLAGS_ALL_COMMON = \
-I$(abs_builddir) \
-I$(abs_srcdir) \
@ -97,7 +99,7 @@ bin_PROGRAMS = moo
moo_SOURCES = main.c
moo_CPPFLAGS = $(CPPFLAGS_LIB_COMMON)
moo_LDFLAGS = $(LDFLAGS_LIB_COMMON)
moo_LDADD = $(LIBADD_LIB_COMMON) -lmoo -lpthread
moo_LDADD = $(LIBADD_LIB_COMMON) -lmoo $(PTHREAD_LIBS)
if ENABLE_STATIC_MODULE
moo_DEPENDENCIES = libmoo.la
endif

View File

@ -102,7 +102,8 @@ host_triplet = @host@
@ENABLE_MOD_X11_TRUE@@ENABLE_STATIC_MODULE_TRUE@am__append_12 = -lmoo-x11
@ENABLE_MOD_X11_TRUE@@ENABLE_STATIC_MODULE_TRUE@am__append_13 = $(abs_builddir)/../mod/libmoo-x11.la
bin_PROGRAMS = moo$(EXEEXT)
@ENABLE_STATIC_MODULE_FALSE@moo_DEPENDENCIES = $(am__DEPENDENCIES_3)
@ENABLE_STATIC_MODULE_FALSE@moo_DEPENDENCIES = $(am__DEPENDENCIES_3) \
@ENABLE_STATIC_MODULE_FALSE@ $(am__DEPENDENCIES_1)
subdir = lib
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(srcdir)/moo-cfg.h.in $(top_srcdir)/ac/depcomp \
@ -110,10 +111,11 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/argz.m4 \
$(top_srcdir)/m4/ax_cxx_namespace.m4 \
$(top_srcdir)/m4/ax_numval.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
$(top_srcdir)/m4/ax_numval.m4 $(top_srcdir)/m4/ax_pthread.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltdl.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@ -334,6 +336,9 @@ PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
PACKAGE_VERSION_PATCH = @PACKAGE_VERSION_PATCH@
PATH_SEPARATOR = @PATH_SEPARATOR@
PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_LIBS = @PTHREAD_LIBS@
QUADMATH_LIBS = @QUADMATH_LIBS@
RANLIB = @RANLIB@
SED = @SED@
@ -356,6 +361,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
ax_pthread_config = @ax_pthread_config@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@ -401,6 +407,7 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = nostdinc
AM_CFLAGS = $(PTHREAD_CFLAGS)
CPPFLAGS_ALL_COMMON = \
-I$(abs_builddir) \
-I$(abs_srcdir) \
@ -459,7 +466,7 @@ libmoo_la_LIBADD = $(LIBADD_LIB_COMMON) $(am__append_5) \
moo_SOURCES = main.c
moo_CPPFLAGS = $(CPPFLAGS_LIB_COMMON)
moo_LDFLAGS = $(LDFLAGS_LIB_COMMON)
moo_LDADD = $(LIBADD_LIB_COMMON) -lmoo -lpthread
moo_LDADD = $(LIBADD_LIB_COMMON) -lmoo $(PTHREAD_LIBS)
@ENABLE_STATIC_MODULE_TRUE@moo_DEPENDENCIES = libmoo.la
all: moo-cfg.h
$(MAKE) $(AM_MAKEFLAGS) all-am

View File

@ -309,7 +309,7 @@ void moo_seterrwithsyserr (moo_t* moo, int syserr)
{
moo_bch_t msgbuf[64];
strerror_r (syserr, msgbuf, MOO_COUNTOF(msgbuf));
moo_seterrbfmt (moo, moo_syserr_to_errnum(errno), "%s", msgbuf);
moo_seterrbfmt (moo, moo_syserr_to_errnum(errno), "%hs", msgbuf);
}
/* --------------------------------------------------------------------------

View File

@ -53,10 +53,10 @@ static MOO_INLINE const char* proc_state_to_string (int state)
* proably depending on the object memory size? */
#define SEM_LIST_INC 256
#define SEM_HEAP_INC 256
#define SEM_IO_INC 256
#define SEM_IO_TUPLE_INC 256
#define SEM_LIST_MAX (SEM_LIST_INC * 1000)
#define SEM_HEAP_MAX (SEM_HEAP_INC * 1000)
#define SEM_IO_MAX (SEM_IO_INC * 1000)
#define SEM_IO_TUPLE_MAX (SEM_IO_TUPLE_INC * 1000)
#define SEM_HEAP_PARENT(x) (((x) - 1) / 2)
#define SEM_HEAP_LEFT(x) ((x) * 2 + 1)
@ -123,7 +123,7 @@ static MOO_INLINE const char* proc_state_to_string (int state)
# define __PRIMITIVE_NAME__ (&__FUNCTION__[0])
#endif
static void signal_io_semaphore (moo_t* moo, moo_ooi_t mask, void* ctx);
static void signal_io_semaphore (moo_t* moo, /*moo_ooi_t io_handle,*/ moo_ooi_t mask, void* data);
static int send_message (moo_t* moo, moo_oop_char_t selector, int to_super, moo_ooi_t nargs);
static int send_message_with_str (moo_t* moo, const moo_ooch_t* nameptr, moo_oow_t namelen, int to_super, moo_ooi_t nargs);
@ -757,6 +757,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 semaphore that belongs to the
@ -829,6 +830,7 @@ 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 */
@ -1023,6 +1025,7 @@ static void delete_from_sem_heap (moo_t* moo, moo_ooi_t index)
MOO_ASSERT (moo, index >= 0 && index < moo->sem_heap_count);
sem = moo->sem_heap[index];
sem->heap_index = MOO_SMOOI_TO_OOP(-1);
moo->sem_heap_count--;
@ -1059,90 +1062,162 @@ static void update_sem_heap (moo_t* moo, moo_ooi_t index, moo_oop_semaphore_t ne
}
#endif
static int add_to_sem_io (moo_t* moo, moo_oop_semaphore_t sem)
static int add_to_sem_io (moo_t* moo, moo_oop_semaphore_t sem, moo_ooi_t io_handle, moo_ooi_t io_mask)
{
moo_ooi_t index;
int n;
int n, tuple_added = 0;
moo_ooi_t new_mask;
if (moo->sem_io_count >= SEM_IO_MAX)
MOO_ASSERT (moo, (sem->io_index == (moo_oop_t)moo->_nil) || (MOO_OOP_IS_SMOOI(sem->io_index) && sem->io_index == MOO_SMOOI_TO_OOP(-1)));
MOO_ASSERT (moo, sem->io_handle == (moo_oop_t)moo->_nil);
MOO_ASSERT (moo, sem->io_mask == (moo_oop_t)moo->_nil);
MOO_ASSERT (moo, io_mask == MOO_SEMAPHORE_IO_MASK_INPUT || io_mask == MOO_SEMAPHORE_IO_MASK_OUTPUT); // TOOD: consider changing this to an error
if (io_handle < 0 || io_handle >= MOO_COUNTOF(moo->sem_io_map)) /* TODO: change the condition when sem_io_map changes to a dynamic structure */
{
moo_seterrnum (moo, MOO_ESHFULL);
moo_seterrbfmt (moo, MOO_EINVAL, "handle %zd out of supported range", io_handle);
return -1;
}
if (moo->sem_io_count >= moo->sem_io_capa)
index = moo->sem_io_map[io_handle]; /* TODO: make it dynamic */
if (index <= -1)
{
moo_oow_t new_capa;
moo_oop_semaphore_t* tmp;
if (moo->sem_io_tuple_count >= SEM_IO_TUPLE_MAX)
{
moo_seterrbfmt (moo, MOO_ESHFULL, "too many IO semaphore tuples"); /* TODO: change error code */
return -1;
}
/* no overflow check when calculating the new capacity
* owing to SEM_IO_MAX check above */
new_capa = moo->sem_io_capa + SEM_IO_INC;
tmp = moo_reallocmem (moo, moo->sem_io, MOO_SIZEOF(moo_oop_semaphore_t) * new_capa);
if (!tmp) return -1;
if (moo->sem_io_tuple_count >= moo->sem_io_tuple_capa)
{
moo_oow_t new_capa;
moo_sem_tuple_t* tmp;
moo->sem_io = tmp;
moo->sem_io_capa = new_capa;
}
/* no overflow check when calculating the new capacity
* owing to SEM_IO_TUPLE_MAX check above */
new_capa = moo->sem_io_tuple_capa + SEM_IO_TUPLE_INC;
tmp = moo_reallocmem (moo, moo->sem_io, MOO_SIZEOF(moo_sem_tuple_t) * new_capa);
if (!tmp) return -1;
MOO_ASSERT (moo, moo->sem_io_count <= MOO_SMOOI_MAX);
MOO_ASSERT (moo, sem->io_index == MOO_SMOOI_TO_OOP(-1));
MOO_MEMSET (&tmp[moo->sem_io_tuple_capa], 0, MOO_SIZEOF(moo_sem_tuple_t) * (new_capa - moo->sem_io_tuple_capa));
moo->sem_io = tmp;
moo->sem_io_tuple_capa = new_capa;
}
index = moo->sem_io_count;
moo->sem_io[index] = sem;
sem->io_index = MOO_SMOOI_TO_OOP(index);
moo->sem_io_count++;
MOO_ASSERT (moo, moo->sem_io_tuple_count <= MOO_SMOOI_MAX);
index = moo->sem_io_tuple_count;
moo_pushtmp (moo, (moo_oop_t*)&sem);
n = moo->vmprim.vm_muxadd (moo, sem);
moo_poptmp (moo);
if (n <= -1)
{
/* roll back */
sem->io_index = MOO_SMOOI_TO_OOP(-1);
moo->sem_io_count--;
tuple_added = 1;
new_mask = io_mask;
moo_pushtmp (moo, (moo_oop_t*)&sem);
n = moo->vmprim.vm_muxadd(moo, io_handle, new_mask, (void*)index);
moo_poptmp (moo);
}
else
{
/* update the number of IO semaphores in a group if necessary */
if ((moo_oop_t)sem->group != moo->_nil)
new_mask = moo->sem_io[index].mask; /* existing mask */
new_mask |= io_mask;
if (new_mask == moo->sem_io[index].mask)
{
moo_ooi_t count;
count = MOO_OOP_TO_SMOOI(sem->group->sem_io_count);
count++;
sem->group->sem_io_count = MOO_SMOOI_TO_OOP(count);
moo_oop_semaphore_t oldsem;
if (moo->sem_io[index].mask & MOO_SEMAPHORE_IO_MASK_INPUT)
oldsem = moo->sem_io[index].in;
else
oldsem = moo->sem_io[index].out;
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(oldsem->io_index) && MOO_OOP_TO_SMOOI(oldsem->io_index) == index);
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(oldsem->io_handle));
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(oldsem->io_mask));
moo_seterrbfmt (moo, MOO_EINVAL, "handle %zd already linked with a semaphore", MOO_OOP_TO_SMOOI(oldsem->io_handle));
return -1;
}
moo_pushtmp (moo, (moo_oop_t*)&sem);
n = moo->vmprim.vm_muxmod(moo, io_handle, new_mask, index);
moo_poptmp (moo);
}
return n;
}
static MOO_INLINE int modify_in_sem_io (moo_t* moo, moo_oop_semaphore_t sem)
{
return moo->vmprim.vm_muxmod (moo, sem);
}
static int delete_from_sem_io (moo_t* moo, moo_ooi_t index)
{
moo_oop_semaphore_t sem;
int x;
MOO_ASSERT (moo, index >= 0 && index < moo->sem_io_count);
sem = moo->sem_io[index];
MOO_ASSERT (moo, index == MOO_OOP_TO_SMOOI(sem->io_index));
moo_pushtmp (moo, (moo_oop_t*)&sem);
x = moo->vmprim.vm_muxdel (moo, sem);
moo_poptmp (moo);
if (x <= -1)
if (n <= -1)
{
MOO_DEBUG2 (moo, "Failed to delete IO semaphore at index %zd on handle %zd\n", index, MOO_OOP_TO_SMOOI(sem->io_handle));
MOO_DEBUG3 (moo, "Failed to add IO semaphore at index %zd on handle %zd mask %zx\n", index, io_handle, io_mask);
return -1;
}
MOO_DEBUG2 (moo, "Deleted IO semaphore at index %zd on handle %zd\n", index, MOO_OOP_TO_SMOOI(sem->io_handle));
MOO_DEBUG3 (moo, "Added IO semaphore at index %zd on handle %zd mask %zx\n", index, io_handle, io_mask);
moo->sem_io_map[io_handle] = index;
sem->io_index = MOO_SMOOI_TO_OOP(index);
sem->io_handle = MOO_SMOOI_TO_OOP(io_handle);
sem->io_mask = MOO_SMOOI_TO_OOP(io_mask);
moo->sem_io[index].mask = new_mask;
/* successfully added the handle to the system multiplexer */
if (io_mask == MOO_SEMAPHORE_IO_MASK_INPUT)
{
moo->sem_io[index].in = sem;
}
else /*if (io_mask == MOO_SEMAPHORE_IO_MASK_OUTPUT)*/
{
moo->sem_io[index].out = sem;
}
moo->sem_io_count++;
if (tuple_added) moo->sem_io_tuple_count++;
/* update the number of IO semaphores in a group if necessary */
if ((moo_oop_t)sem->group != moo->_nil)
{
moo_ooi_t count;
count = MOO_OOP_TO_SMOOI(sem->group->sem_io_count);
count++;
sem->group->sem_io_count = MOO_SMOOI_TO_OOP(count);
}
return 0;
}
static int delete_from_sem_io (moo_t* moo, moo_oop_semaphore_t sem)
{
moo_ooi_t index;
moo_ooi_t new_mask, io_handle;
int x;
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_index));
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_handle));
index = MOO_OOP_TO_SMOOI(sem->io_index);
MOO_ASSERT (moo, index >= 0 && index < moo->sem_io_count);
new_mask = moo->sem_io[index].mask;
new_mask &= ~MOO_OOP_TO_SMOOI(sem->io_mask); /* calculate the new mask after deletion */
new_mask &= MOO_SEMAPHORE_IO_MASK_INPUT | MOO_SEMAPHORE_IO_MASK_OUTPUT; /* for sanity */
io_handle = MOO_OOP_TO_SMOOI(sem->io_handle);
if (io_handle < 0 || io_handle >= MOO_COUNTOF(moo->sem_io_map)) /* TODO: change the condition when sem_io_map changes to a dynamic structure */
{
moo_seterrbfmt (moo, MOO_EINVAL, "handle %zd out of supported range", io_handle);
return -1;
}
moo_pushtmp (moo, (moo_oop_t*)&sem);
x = new_mask? moo->vmprim.vm_muxmod(moo, io_handle, new_mask, (void*)index):
moo->vmprim.vm_muxdel(moo, io_handle);
moo_poptmp (moo);
if (x <= -1)
{
MOO_DEBUG2 (moo, "Failed to delete IO semaphore at index %zd on handle %zd - %js\n", index, sem->io_handle);
return -1;
}
MOO_DEBUG3 (moo, "Deleted IO semaphore at index %zd on handle %zd mask %zx\n", index, io_handle, MOO_OOP_TO_SMOOI(sem->io_mask));
sem->io_index = MOO_SMOOI_TO_OOP(-1);
sem->io_mask = moo->_nil;
sem->io_handle = moo->_nil;
moo->sem_io_count--;
if ((moo_oop_t)sem->group != moo->_nil)
{
moo_ooi_t count;
@ -1152,73 +1227,76 @@ static int delete_from_sem_io (moo_t* moo, moo_ooi_t index)
sem->group->sem_io_count = MOO_SMOOI_TO_OOP(count);
}
if (/*moo->sem_io_count > 0 &&*/ index != moo->sem_io_count)
if (new_mask)
{
moo_oop_semaphore_t lastsem;
moo->sem_io[index].mask = new_mask;
}
else
{
moo->sem_io_map[io_handle] = -1;
/* move the last item to the deletion position for compaction */
lastsem = moo->sem_io[moo->sem_io_count];
lastsem->io_index = MOO_SMOOI_TO_OOP(index);
moo->sem_io[index] = lastsem;
moo->sem_io_tuple_count--;
moo_pushtmp (moo, (moo_oop_t*)&lastsem);
x = moo->vmprim.vm_muxmod (moo, lastsem);
moo_poptmp (moo);
if (x <= -1)
if (/*moo->sem_io_count > 0 &&*/ index != moo->sem_io_count)
{
/* unfortunately, i can't roll back gracefully. i nullify the delete slot instead of compaction */
MOO_LOG3 (moo, MOO_LOG_WARN, "Warning - IO sempahore migration failure from %zd to %zd on handle %zd - expect VM memory waste\n", moo->sem_io_count, MOO_OOP_TO_SMOOI(lastsem->io_index), MOO_OOP_TO_SMOOI(lastsem->io_handle));
lastsem->io_index = MOO_SMOOI_TO_OOP(moo->sem_io_count);
moo->sem_io[moo->sem_io_count] = lastsem;
moo->sem_io_count++;
moo->sem_io[index] = (moo_oop_semaphore_t)moo->_nil;
}
else
{
MOO_DEBUG3 (moo, "Migrated IO semaphore from index %zd to %zd on handle %zd\n", moo->sem_io_count, MOO_OOP_TO_SMOOI(lastsem->io_index), MOO_OOP_TO_SMOOI(lastsem->io_handle));
moo->sem_io[index] = moo->sem_io[moo->sem_io_count];
if (moo->sem_io[index].mask & MOO_SEMAPHORE_IO_MASK_INPUT)
moo->sem_io[index].in->io_index = MOO_SMOOI_TO_OOP(index);
if (moo->sem_io[index].mask & MOO_SEMAPHORE_IO_MASK_OUTPUT)
moo->sem_io[index].out->io_index = MOO_SMOOI_TO_OOP(index);
}
}
return 0;
}
static void signal_io_semaphore (moo_t* moo, moo_ooi_t mask, void* ctx)
static void _signal_io_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
{
moo_oop_process_t proc;
proc = signal_semaphore (moo, sem);
if (moo->processor->active == moo->nil_process && (moo_oop_t)proc != moo->_nil)
{
/* this is the only runnable process.
* switch the process to the running state.
* it uses wake_process() instead of
* switch_to_process() as there is no running
* process at this moment */
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE));
MOO_ASSERT (moo, proc == moo->processor->runnable.first);
#if 0
wake_process (moo, proc); /* switch to running */
moo->proc_switched = 1;
#else
switch_to_process_from_nil (moo, proc);
#endif
}
}
static void signal_io_semaphore (moo_t* moo, /*moo_ooi_t io_handle,*/ moo_ooi_t mask, void* ctx)
{
moo_oow_t sem_io_index = (moo_oow_t)ctx;
/* TODO: sanity check on the index. conditional handling on mask */
if (sem_io_index < moo->sem_io_count)
if (sem_io_index < moo->sem_io_count /*&&
io_handle >= 0 && io_handle < MOO_COUNTOF(moo->sem_io_map) &&
moo->sem_io_map[io_handle] == sem_io_index*/)
{
moo_oop_semaphore_t sem;
moo_oop_process_t proc;
sem = moo->sem_io[sem_io_index];
if ((moo_oop_t)sem == moo->_nil)
sem = moo->sem_io[sem_io_index].in;
if (sem && (mask & (MOO_SEMAPHORE_IO_MASK_INPUT | MOO_SEMAPHORE_IO_MASK_HANGUP | MOO_SEMAPHORE_IO_MASK_ERROR)))
{
/* it's a nullified slot for migration failure in delete_from_sem_io() */
goto invalid_semaphore;
_signal_io_semaphore (moo, sem);
}
proc = signal_semaphore (moo, sem);
if (moo->processor->active == moo->nil_process && (moo_oop_t)proc != moo->_nil)
sem = moo->sem_io[sem_io_index].out;
if (sem && (mask & MOO_SEMAPHORE_IO_MASK_OUTPUT))
{
/* this is the only runnable process.
* switch the process to the running state.
* it uses wake_process() instead of
* switch_to_process() as there is no running
* process at this moment */
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE));
MOO_ASSERT (moo, proc == moo->processor->runnable.first);
#if 0
wake_process (moo, proc); /* switch to running */
moo->proc_switched = 1;
#else
switch_to_process_from_nil (moo, proc);
#endif
_signal_io_semaphore (moo, sem);
}
}
else
@ -2392,7 +2470,6 @@ static moo_pfrc_t __system_add_io_semaphore (moo_t* moo, moo_ooi_t nargs, moo_oo
fd = MOO_STACK_GETARG(moo, nargs, 1);
sem = (moo_oop_semaphore_t)MOO_STACK_GETARG(moo, nargs, 0);
if (!moo_iskindof(moo, (moo_oop_t)sem, moo->_semaphore))
{
moo_seterrbfmt (moo, MOO_EINVAL, "parameter not a kind of semaphore - %O", sem);
@ -2401,49 +2478,26 @@ static moo_pfrc_t __system_add_io_semaphore (moo_t* moo, moo_ooi_t nargs, moo_oo
if (!MOO_OOP_IS_SMOOI(fd))
{
moo_seterrbfmt (moo, MOO_EINVAL, "IO handle not a small integer - %O", fd);
moo_seterrbfmt (moo, MOO_EINVAL, "handle not a small integer - %O", fd);
return MOO_PF_FAILURE;
}
if (MOO_OOP_IS_SMOOI(sem->io_index) && sem->io_index != MOO_SMOOI_TO_OOP(-1) && sem->io_handle == fd)
if (MOO_OOP_IS_SMOOI(sem->io_index) && sem->io_index != MOO_SMOOI_TO_OOP(-1))
{
moo_ooi_t old_mask;
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_handle) && MOO_OOP_TO_SMOOI(sem->io_handle) >= 0);
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_mask) && MOO_OOP_TO_SMOOI(sem->io_mask) > 0);
/* the semaphore is already linked with the requested IO handle */
old_mask = MOO_OOP_TO_SMOOI(sem->io_mask);
if (old_mask != mask)
{
sem->io_mask = MOO_SMOOI_TO_OOP(mask);
if (modify_in_sem_io(moo, sem) <= -1)
{
sem->io_mask = MOO_SMOOI_TO_OOP(old_mask);
moo_seterrbfmt (moo, moo->errnum, "cannot modify the handle %zd in the multiplexer", MOO_OOP_TO_SMOOI(sem->io_handle));
return MOO_PF_FAILURE;
}
}
moo_seterrbfmt (moo, MOO_EINVAL, "semaphore already linked with a handle %zd", MOO_OOP_TO_SMOOI(sem->io_handle));
return MOO_PF_FAILURE;
}
else
{
if (MOO_OOP_IS_SMOOI(sem->io_index) && sem->io_index != MOO_SMOOI_TO_OOP(-1))
{
/* remove it if it's already added for IO */
if (delete_from_sem_io(moo, MOO_OOP_TO_SMOOI(sem->io_index)) <= -1)
{
moo_seterrbfmt (moo, moo->errnum, "cannot delete the handle %zd from the multiplexer", MOO_OOP_TO_SMOOI(sem->io_handle));
return MOO_PF_FAILURE;
}
MOO_ASSERT (moo, sem->io_index == MOO_SMOOI_TO_OOP(-1));
}
sem->io_handle = fd;
sem->io_mask = MOO_SMOOI_TO_OOP(mask);
if (add_to_sem_io(moo, sem) <= -1)
{
moo_seterrbfmt (moo, moo->errnum, "cannot add the handle %zd to the multiplexer", MOO_OOP_TO_SMOOI(sem->io_handle));
return MOO_PF_FAILURE;
}
/*sem->io_handle = fd;
sem->io_mask = MOO_SMOOI_TO_OOP(mask);*/
if (add_to_sem_io(moo, sem, MOO_OOP_TO_SMOOI(fd), mask) <= -1)
{
moo_copyoocstr (moo->errmsg.buf2, MOO_COUNTOF(moo->errmsg.buf2), moo->errmsg.buf);
moo_seterrbfmt (moo, moo->errnum, "cannot add the handle %zd to the multiplexer - %js", MOO_OOP_TO_SMOOI(fd), moo->errmsg.buf2);
return MOO_PF_FAILURE;
}
MOO_STACK_SETRETTORCV (moo, nargs); /* ^self */
@ -2500,9 +2554,10 @@ static moo_pfrc_t pf_system_remove_semaphore (moo_t* moo, moo_ooi_t nargs)
if (MOO_OOP_IS_SMOOI(sem->io_index) && sem->io_index != MOO_SMOOI_TO_OOP(-1))
{
/* the semaphore is associated with IO */
if (delete_from_sem_io (moo, MOO_OOP_TO_SMOOI(sem->io_index)) <= -1)
if (delete_from_sem_io (moo, sem) <= -1)
{
moo_seterrbfmt (moo, moo->errnum, "cannot delete the handle %zd from the multiplexer", MOO_OOP_TO_SMOOI(sem->io_handle));
moo_copyoocstr (moo->errmsg.buf2, MOO_COUNTOF(moo->errmsg.buf2), moo->errmsg.buf);
moo_seterrbfmt (moo, moo->errnum, "cannot delete the handle %zd from the multiplexer - %js", MOO_OOP_TO_SMOOI(sem->io_handle), moo->errmsg.buf2);
return MOO_PF_FAILURE;
}

View File

@ -898,7 +898,10 @@ void moo_gc (moo_t* moo)
for (i = 0; i < moo->sem_io_count; i++)
{
moo->sem_io[i] = (moo_oop_semaphore_t)moo_moveoop (moo, (moo_oop_t)moo->sem_io[i]);
if (moo->sem_io[i].in)
moo->sem_io[i].in = (moo_oop_semaphore_t)moo_moveoop (moo, (moo_oop_t)moo->sem_io[i].in);
if (moo->sem_io[i].out)
moo->sem_io[i].out = (moo_oop_semaphore_t)moo_moveoop (moo, (moo_oop_t)moo->sem_io[i].out);
}
moo->sem_gcfin = (moo_oop_semaphore_t)moo_moveoop (moo, (moo_oop_t)moo->sem_gcfin);

View File

@ -855,7 +855,7 @@ static MOO_INLINE void destroy_poll_data_space (moo_t* moo)
#endif
static int _add_poll_fd (moo_t* moo, int fd, int event_mask, moo_oow_t event_data)
static int _add_poll_fd (moo_t* moo, int fd, int event_mask, void* event_data)
{
#if defined(USE_DEVPOLL)
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
@ -869,7 +869,7 @@ static int _add_poll_fd (moo_t* moo, int fd, int event_mask, moo_oow_t event_dat
ev.revents = 0;
if (write (xtn->ep, &ev, MOO_SIZEOF(ev)) != MOO_SIZEOF(ev))
{
moo_syserr_to_errnum (errno);
moo_seterrwithsyserr (moo, errno);
MOO_DEBUG2 (moo, "Cannot add file descriptor %d to devpoll - %hs\n", fd, strerror(errno));
return -1;
}
@ -890,9 +890,10 @@ static int _add_poll_fd (moo_t* moo, int fd, int event_mask, moo_oow_t event_dat
ev.events |= EPOLLET;
#endif
ev.data.ptr = (void*)event_data;
if (epoll_ctl (xtn->ep, EPOLL_CTL_ADD, fd, &ev) == -1)
if (epoll_ctl(xtn->ep, EPOLL_CTL_ADD, fd, &ev) == -1)
{
moo_syserr_to_errnum (errno);
moo_seterrwithsyserr (moo, errno);
MOO_DEBUG2 (moo, "Cannot add file descriptor %d to epoll - %hs\n", fd, strerror(errno));
return -1;
}
@ -1050,7 +1051,7 @@ static int _del_poll_fd (moo_t* moo, int fd)
}
static int _mod_poll_fd (moo_t* moo, int fd, int event_mask, moo_oow_t event_data)
static int _mod_poll_fd (moo_t* moo, int fd, int event_mask, void* event_data)
{
#if defined(USE_DEVPOLL)
@ -1073,7 +1074,7 @@ static int _mod_poll_fd (moo_t* moo, int fd, int event_mask, moo_oow_t event_dat
ev.data.ptr = (void*)event_data;
if (epoll_ctl (xtn->ep, EPOLL_CTL_MOD, fd, &ev) == -1)
{
moo_syserr_to_errnum (errno);
moo_seterrwithsyserr (moo, errno);
MOO_DEBUG2 (moo, "Cannot modify file descriptor %d in epoll - %hs\n", fd, strerror(errno));
return -1;
}
@ -1213,7 +1214,7 @@ static int vm_startup (moo_t* moo)
if (flag >= 0) fcntl (xtn->p[1], F_SETFL, flag | O_NONBLOCK);
#endif
if (_add_poll_fd(moo, xtn->p[0], XPOLLIN, MOO_TYPE_MAX(moo_oow_t)) <= -1) goto oops;
if (_add_poll_fd(moo, xtn->p[0], XPOLLIN, (void*)MOO_TYPE_MAX(moo_oow_t)) <= -1) goto oops;
pthread_mutex_init (&xtn->ev.mtx, MOO_NULL);
pthread_cond_init (&xtn->ev.cnd, MOO_NULL);
@ -1381,57 +1382,45 @@ static void vm_gettime (moo_t* moo, moo_ntime_t* now)
#endif
static int vm_muxadd (moo_t* moo, moo_oop_semaphore_t sem)
static int vm_muxadd (moo_t* moo, moo_ooi_t io_handle, moo_ooi_t mask, void* ctx)
{
moo_ooi_t mask;
int event_mask;
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_index));
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_handle));
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_mask));
mask = MOO_OOP_TO_SMOOI(sem->io_mask);
event_mask = 0; /*EPOLLET; */ /* TODO: use edge trigger(EPOLLLET)? */
if (mask & MOO_SEMAPHORE_IO_MASK_INPUT) event_mask |= XPOLLIN;
if (mask & MOO_SEMAPHORE_IO_MASK_OUTPUT) event_mask |= XPOLLOUT;
if (event_mask == 0)
{
MOO_DEBUG2 (moo, "<vm_muxadd> Invalid semaphore mask %zd on handle %zd\n", mask, MOO_OOP_TO_SMOOI(sem->io_handle));
moo_seterrnum (moo, MOO_EINVAL);
MOO_DEBUG2 (moo, "<vm_muxadd> Invalid semaphore mask %zd on handle %zd\n", mask, io_handle);
moo_seterrbfmt (moo, MOO_EINVAL, "invalid semaphore mask %zd on handle %zd", mask, io_handle);
return -1;
}
return _add_poll_fd (moo, MOO_OOP_TO_SMOOI(sem->io_handle), event_mask, MOO_OOP_TO_SMOOI(sem->io_index));
return _add_poll_fd (moo, io_handle, event_mask, ctx);
}
static int vm_muxmod (moo_t* moo, moo_oop_semaphore_t sem)
static int vm_muxmod (moo_t* moo, moo_ooi_t io_handle, moo_ooi_t mask, void* ctx)
{
moo_ooi_t mask;
int event_mask;
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_index));
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_handle));
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(sem->io_mask));
mask = MOO_OOP_TO_SMOOI(sem->io_mask);
event_mask = 0; /*EPOLLET; */ /* TODO: use edge trigger(EPOLLLET)? */
if (mask & MOO_SEMAPHORE_IO_MASK_INPUT) event_mask |= XPOLLIN;
if (mask & MOO_SEMAPHORE_IO_MASK_OUTPUT) event_mask |= XPOLLOUT;
if (event_mask == 0)
{
MOO_DEBUG2 (moo, "<vm_muxadd> Invalid semaphore mask %zd on handle %zd\n", mask, MOO_OOP_TO_SMOOI(sem->io_handle));
moo_seterrnum (moo, MOO_EINVAL);
MOO_DEBUG2 (moo, "<vm_muxadd> Invalid semaphore mask %zd on handle %zd\n", mask, io_handle);
moo_seterrbfmt (moo, MOO_EINVAL, "invalid semaphore mask %zd on handle %zd", mask, io_handle);
return -1;
}
return _mod_poll_fd (moo, MOO_OOP_TO_SMOOI(sem->io_handle), event_mask, MOO_OOP_TO_SMOOI(sem->io_index));
return _mod_poll_fd (moo, io_handle, event_mask, ctx);
}
static int vm_muxdel (moo_t* moo, moo_oop_semaphore_t sem)
static int vm_muxdel (moo_t* moo, moo_ooi_t io_handle)
{
return _del_poll_fd (moo, MOO_OOP_TO_SMOOI(sem->io_handle));
return _del_poll_fd (moo, io_handle);
}
#if defined(USE_THREAD)
@ -2163,12 +2152,12 @@ int main (int argc, char* argv[])
moo_bci_t c;
static moo_bopt_lng_t lopt[] =
{
{ ":log", 'l' },
{ ":memsize", 'm' },
{ ":log", 'l' },
{ ":memsize", 'm' },
#if !defined(NDEBUG)
{ ":debug", '\0' }, /* NOTE: there is no short option for --debug */
{ ":debug", '\0' }, /* NOTE: there is no short option for --debug */
#endif
{ MOO_NULL, '\0' }
{ MOO_NULL, '\0' }
};
static moo_bopt_t opt =
{
@ -2207,6 +2196,7 @@ int main (int argc, char* argv[])
break;
case '\0':
#if !defined(NDEBUG)
if (moo_compbcstr(opt.lngopt, "debug") == 0)
{
@ -2214,6 +2204,7 @@ int main (int argc, char* argv[])
break;
}
#endif
goto print_usage;
case ':':

View File

@ -172,6 +172,12 @@
/* Define if libtool can extract symbol lists from object files. */
#undef HAVE_PRELOADED_SYMBOLS
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD
/* Have PTHREAD_PRIO_INHERIT. */
#undef HAVE_PTHREAD_PRIO_INHERIT
/* Define to 1 if you have the `quadmath_snprintf' function. */
#undef HAVE_QUADMATH_SNPRINTF
@ -483,6 +489,10 @@
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#undef PTHREAD_CREATE_JOINABLE
/* The size of `char', as computed by sizeof. */
#undef SIZEOF_CHAR

View File

@ -85,6 +85,7 @@ static void fill_bigint_tables (moo_t* moo)
int moo_init (moo_t* moo, moo_mmgr_t* mmgr, moo_oow_t heapsz, const moo_vmprim_t* vmprim)
{
int modtab_inited = 0;
int i;
MOO_MEMSET (moo, 0, MOO_SIZEOF(*moo));
moo->mmgr = mmgr;
@ -130,6 +131,9 @@ int moo_init (moo_t* moo, moo_mmgr_t* mmgr, moo_oow_t heapsz, const moo_vmprim_t
moo->proc_map_free_first = -1;
moo->proc_map_free_last = -1;
for (i = 0; i < MOO_COUNTOF(moo->sem_io_map); i++) moo->sem_io_map[i] = -1;
return 0;
oops:
@ -178,7 +182,8 @@ void moo_fini (moo_t* moo)
if (moo->sem_io)
{
moo_freemem (moo, moo->sem_io);
moo->sem_io_capa = 0;
moo->sem_io_tuple_capa = 0;
moo->sem_io_tuple_count = 0;
moo->sem_io_count = 0;
moo->sem_io_wait_count = 0;
}

View File

@ -123,7 +123,7 @@ enum moo_trait_t
MOO_NOGC = (1 << 8),
/* wait for running process when exiting from the main method */
MOO_AWAIT_PROCS = (1 << 9)
MOO_AWAIT_PROCS = (1 << 9),
};
typedef enum moo_trait_t moo_trait_t;
@ -823,6 +823,7 @@ struct moo_semaphore_t
moo_oop_t io_mask; /* SmallInteger */
moo_oop_t signal_action;
moo_oop_semaphore_group_t group; /* nil or belonging semaphore group */
struct
{
@ -925,9 +926,9 @@ typedef int (*moo_vmprim_startup_t) (moo_t* moo);
typedef void (*moo_vmprim_cleanup_t) (moo_t* moo);
typedef void (*moo_vmprim_gettime_t) (moo_t* moo, moo_ntime_t* now);
typedef int (*moo_vmprim_muxadd_t) (moo_t* moo, moo_oop_semaphore_t sem);
typedef int (*moo_vmprim_muxmod_t) (moo_t* moo, moo_oop_semaphore_t sem);
typedef int (*moo_vmprim_muxdel_t) (moo_t* moo, moo_oop_semaphore_t sem);
typedef int (*moo_vmprim_muxadd_t) (moo_t* moo, moo_ooi_t io_handle, moo_ooi_t mask, void* ctx);
typedef int (*moo_vmprim_muxmod_t) (moo_t* moo, moo_ooi_t io_handle, moo_ooi_t mask, void* ctx);
typedef int (*moo_vmprim_muxdel_t) (moo_t* moo, moo_ooi_t sem);
typedef void (*moo_vmprim_muxwait_cb_t) (moo_t* moo, moo_ooi_t mask, void* ctx);
typedef void (*moo_vmprim_muxwait_t) (moo_t* moo, const moo_ntime_t* duration, moo_vmprim_muxwait_cb_t muxwcb);
@ -1097,6 +1098,14 @@ struct moo_sbuf_t
};
typedef struct moo_sbuf_t moo_sbuf_t;
struct moo_sem_tuple_t
{
moo_oop_semaphore_t in;
moo_oop_semaphore_t out;
moo_ooi_t mask;
};
typedef struct moo_sem_tuple_t moo_sem_tuple_t;
typedef struct moo_finalizable_t moo_finalizable_t;
struct moo_finalizable_t
{
@ -1123,6 +1132,7 @@ struct moo_t
struct
{
moo_ooch_t buf2[2048];
moo_ooch_t buf[2048];
moo_oow_t len;
} errmsg;
@ -1242,11 +1252,17 @@ struct moo_t
moo_oow_t sem_heap_capa;
/* semaphores for I/O handling. plain array */
moo_oop_semaphore_t* sem_io;
/*moo_oop_semaphore_t* sem_io;*/
moo_sem_tuple_t* sem_io;
moo_oow_t sem_io_tuple_count;
moo_oow_t sem_io_tuple_capa;
moo_oow_t sem_io_count;
moo_oow_t sem_io_capa;
moo_oow_t sem_io_wait_count;
moo_ooi_t sem_io_map[10240]; /* TODO: make it dynamic */
/* semaphore to notify finalizable objects */
moo_oop_semaphore_t sem_gcfin;
int sem_gcfin_sigreq;