From 5ae166c1d47e49595c50f7629a1cf99f606d465d Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Tue, 31 Oct 2017 07:13:22 +0000 Subject: [PATCH] attempted to fix wrong IO semaphore handling over a semaphore group --- moo/kernel/Process.moo | 25 +++++++++++++++------ moo/kernel/Socket.moo | 26 ++++++++++++---------- moo/kernel/System.moo | 20 ++++++++++++++++- moo/lib/comp.c | 2 +- moo/lib/exec.c | 46 +++++++++++++++++++++++++++++++++++++-- moo/lib/gc.c | 49 +++++++++++++++++++++++++++++++++++------- moo/lib/moo.h | 4 +++- 7 files changed, 141 insertions(+), 31 deletions(-) diff --git a/moo/kernel/Process.moo b/moo/kernel/Process.moo index 135e1bc..204483a 100644 --- a/moo/kernel/Process.moo +++ b/moo/kernel/Process.moo @@ -196,7 +196,8 @@ class SemaphoreGroup(Object) first_sem := nil, last_sem := nil, first_sigsem := nil, - last_sigsem := nil. + last_sigsem := nil, + sem_io_count := 0. (* TODO: good idea to a shortcut way to prohibit a certain method in the heirarchy chain? method(#class,#prohibited) new. @@ -220,12 +221,22 @@ method(#class,#abstract) xxx. => method(#class) xxx { self subclassResponsibilit if (x isError) { thisProcess primError dump. Exception signal: ('Cannot add a semaphore - ' & thisProcess primError) }. ^x } + + method removeSemaphore: sem + { + | x | + x := self _removeSemaphore: sem. + if (x isError) { thisProcess primError dump. Exception signal: ('Cannot remove a semaphore - ' & thisProcess primError) }. + ^x + } + method wait { - | r | - r := self _wait. - if (r signalAction notNil) { r signalAction value: r }. - ^r + | x | + x := self _wait. + if (x isError) { thisProcess primError dump. Exception signal: ('Cannot remove a semaphore - ' & thisProcess primError) }. + if (x signalAction notNil) { x signalAction value: x }. + ^x } method waitWithTimeout: seconds @@ -238,7 +249,7 @@ method(#class,#abstract) xxx. => method(#class) xxx { self subclassResponsibilit ## grant the partial membership to the internal semaphore. ## it's partial because it's not added to self.semarr. ##s _group: self. - self _addSemaphore: s. + self addSemaphore: s. ## arrange the processor to notify upon timeout. Processor signal: s after: seconds. @@ -253,7 +264,7 @@ method(#class,#abstract) xxx. => method(#class) xxx { self subclassResponsibilit ## nullify the membership ##s _group: nil. - self _removeSemaphore: s. + self removeSemaphore: s. ## cancel the notification arrangement in case it didn't time out. Processor unsignal: s. diff --git a/moo/kernel/Socket.moo b/moo/kernel/Socket.moo index 672e322..e3e91eb 100644 --- a/moo/kernel/Socket.moo +++ b/moo/kernel/Socket.moo @@ -52,29 +52,33 @@ extend Socket method asyncConnect: connectBlock { - | s1 s2 sg | + | s1 s2 sg sa | + s1 := Semaphore new. s2 := Semaphore new. - s1 signalAction: [:sem | Processor unsignal: s1. connectBlock value: true]. - s2 signalAction: [:sem | Processor unsignal: s2. connectBlock value: false]. + sa := [:sem | + Processor unsignal: s1. + Processor unsignal: s2. + System removeAsyncSemaphore: s1. + System removeAsyncSemaphore: s2. + connectBlock value: (sem == s1) + ]. + s1 signalAction: sa. + s2 signalAction: sa. + +## TODO: unsignal s1 s2, remove them from System when exception occurs. Processor signal: s1 onOutput: self.handle. Processor signal: s2 after: 10. - sg := SemaphoreGroup new. - sg addSemaphore: s1. - sg addSemaphore: s2. -sg addSemaphore: s1. -sg addSemaphore: 10. -sg addSemaphore: s1. + System addAsyncSemaphore: s1. + System addAsyncSemaphore: s2. if (self _connect(1, 2, 3) isError) { Exception signal: 'Cannot connect to 1,2,3'. }. - - sg wait. } method asyncRead: readBlock diff --git a/moo/kernel/System.moo b/moo/kernel/System.moo index e9bb081..3aa94c1 100644 --- a/moo/kernel/System.moo +++ b/moo/kernel/System.moo @@ -10,10 +10,28 @@ class System(Apex) { + var(#class) asyncsg. + + method(#class) addAsyncSemaphore: sem + { + ^self.asyncsg addSemaphore: sem + } + + method(#class) removeAsyncSemaphore: sem + { + ^self.asyncsg removeSemaphore: sem + } + method(#class) handleAsyncEvent + { + ^self.asyncsg wait. + } + method(#class) startup(class_name, method_name) { | class ret | + self.asyncsg := SemaphoreGroup new. + class := System at: class_name. if (class isError) { @@ -103,7 +121,7 @@ extend System ## System logNl: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'. ## method(#class,#variadic,#primitive) log(level,msg1). - + (* TODO: how to pass all variadic arguments to another variadic methods??? method(#class,#variadic) logInfo (msg1) diff --git a/moo/lib/comp.c b/moo/lib/comp.c index c523fc1..2bc409a 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -945,7 +945,7 @@ static int skip_comment (moo_t* moo) GET_CHAR_TO (moo, c); if (c == MOO_UCI_EOF) goto unterminated; - if (c == '*') goto check_rparen; + if (c == '*') goto check_rparen; /* got another * after * */ if (c == ')') { GET_CHAR (moo); /* keep the first meaningful character in lxc */ diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 422a8ef..e86cd0f 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -889,7 +889,13 @@ static MOO_INLINE moo_oop_t await_semaphore_group (moo_t* moo, moo_oop_semaphore /* link the suspended process to the semaphore group's process list */ chain_into_semaphore (moo, proc, (moo_oop_semaphore_t)semgrp); MOO_ASSERT (moo, semgrp->waiting.last == proc); - /*if (MOO_OOP_TO_SMOOI(semgrp->io_index) >= 0) moo->semgrp_io_wait_count++;*/ + + if (MOO_OOP_TO_SMOOI(semgrp->sem_io_count) >= 0) + { + /* there might be more than 1 IO semaphores in the group + * but i increment moo->sem_io_wait_count by 1 only */ + moo->sem_io_wait_count++; + } /* the current process will get suspended after the caller (mostly a * a primitive function handler) is over as it's added to a suspened @@ -1092,6 +1098,17 @@ static int add_to_sem_io (moo_t* moo, moo_oop_semaphore_t sem) sem->io_index = MOO_SMOOI_TO_OOP(-1); moo->sem_io_count--; } + else + { + /* 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 n; } @@ -1121,8 +1138,16 @@ static int delete_from_sem_io (moo_t* moo, moo_ooi_t index) MOO_DEBUG2 (moo, "Deleted IO semaphore at index %zd on handle %zd\n", index, MOO_OOP_TO_SMOOI(sem->io_handle)); sem->io_index = MOO_SMOOI_TO_OOP(-1); - moo->sem_io_count--; + if ((moo_oop_t)sem->group != moo->_nil) + { + moo_ooi_t count; + count = MOO_OOP_TO_SMOOI(sem->group->sem_io_count); + MOO_ASSERT (moo, count > 0); + count--; + sem->group->sem_io_count = MOO_SMOOI_TO_OOP(count); + } + if (/*moo->sem_io_count > 0 &&*/ index != moo->sem_io_count) { moo_oop_semaphore_t lastsem; @@ -2557,6 +2582,15 @@ static moo_pfrc_t pf_semaphore_group_add_semaphore (moo_t* moo, moo_ooi_t nargs) 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; + + if (MOO_OOP_TO_SMOOI(sem->io_index) >=0) + { + moo_ooi_t count; + count = MOO_OOP_TO_SMOOI(rcv->sem_io_count); + count++; + rcv->sem_io_count = MOO_SMOOI_TO_OOP(count); + } + MOO_STACK_SETRETTORCV (moo, nargs); } else if (sem->group == rcv) @@ -2593,6 +2627,14 @@ static moo_pfrc_t pf_semaphore_group_remove_semaphore (moo_t* moo, moo_ooi_t nar sem->grm.next = (moo_oop_semaphore_t)moo->_nil; sem->group = (moo_oop_semaphore_group_t)moo->_nil; + if (MOO_OOP_TO_SMOOI(sem->io_index) >=0) + { + moo_ooi_t count; + count = MOO_OOP_TO_SMOOI(rcv->sem_io_count); + count--; + rcv->sem_io_count = MOO_SMOOI_TO_OOP(count); + } + MOO_STACK_SETRETTORCV (moo, nargs); } else diff --git a/moo/lib/gc.c b/moo/lib/gc.c index 26af327..9d04b91 100644 --- a/moo/lib/gc.c +++ b/moo/lib/gc.c @@ -76,6 +76,7 @@ struct kernel_class_info_t moo_oow_t len; moo_ooch_t name[20]; int class_flags; + int class_num_classvars; int class_spec_named_instvars; int class_spec_flags; @@ -105,6 +106,7 @@ static kernel_class_info_t kernel_classes[] = 0, 0, 0, + 0, MOO_OBJ_TYPE_OOP, MOO_OFFSETOF(moo_t, _apex) }, @@ -113,13 +115,15 @@ static kernel_class_info_t kernel_classes[] = 0, 0, 0, + 0, MOO_OBJ_TYPE_OOP, MOO_OFFSETOF(moo_t, _undefined_object) }, -#define KCI_CLASS 2 +#define KCI_CLASS 2 /* index to the Class entry in this table */ { 5, { 'C','l','a','s','s' }, MOO_CLASS_SELFSPEC_FLAG_LIMITED, + 0, MOO_CLASS_NAMED_INSTVARS, 1, MOO_OBJ_TYPE_OOP, @@ -130,6 +134,7 @@ static kernel_class_info_t kernel_classes[] = 0, 0, 0, + 0, MOO_OBJ_TYPE_OOP, MOO_OFFSETOF(moo_t, _object) }, @@ -137,6 +142,7 @@ static kernel_class_info_t kernel_classes[] = { 'S','t','r','i','n','g' }, 0, 0, + 0, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_CHAR, MOO_OFFSETOF(moo_t, _string) }, @@ -145,6 +151,7 @@ static kernel_class_info_t kernel_classes[] = { 'S','y','m','b','o','l' }, MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED, 0, + 0, MOO_CLASS_SPEC_FLAG_INDEXED | MOO_CLASS_SPEC_FLAG_IMMUTABLE, MOO_OBJ_TYPE_CHAR, MOO_OFFSETOF(moo_t, _symbol) }, @@ -153,6 +160,7 @@ static kernel_class_info_t kernel_classes[] = { 'A','r','r','a','y' }, 0, 0, + 0, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_OOP, MOO_OFFSETOF(moo_t, _array) }, @@ -161,6 +169,7 @@ static kernel_class_info_t kernel_classes[] = { 'B','y','t','e','A','r','r','a','y' }, 0, 0, + 0, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_BYTE, MOO_OFFSETOF(moo_t, _byte_array) }, @@ -168,6 +177,7 @@ static kernel_class_info_t kernel_classes[] = { 9, { 'S','y','m','b','o','l','S','e','t' }, 0, + 0, MOO_DIC_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP, @@ -176,6 +186,7 @@ static kernel_class_info_t kernel_classes[] = { 10, { 'D','i','c','t','i','o','n','a','r','y' }, 0, + 0, MOO_DIC_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP, @@ -184,6 +195,7 @@ static kernel_class_info_t kernel_classes[] = { 9, { 'N','a','m','e','s','p','a','c','e' }, MOO_CLASS_SELFSPEC_FLAG_LIMITED, + 0, MOO_NSDIC_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP, @@ -192,6 +204,7 @@ static kernel_class_info_t kernel_classes[] = { 14, { 'P','o','o','l','D','i','c','t','i','o','n','a','r','y' }, 0, + 0, MOO_DIC_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP, @@ -200,6 +213,7 @@ static kernel_class_info_t kernel_classes[] = { 16, { 'M','e','t','h','o','d','D','i','c','t','i','o','n','a','r','y' }, 0, + 0, MOO_DIC_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP, @@ -208,6 +222,7 @@ static kernel_class_info_t kernel_classes[] = { 14, { 'C','o','m','p','i','l','e','d','M','e','t','h','o','d' }, 0, + 0, MOO_METHOD_NAMED_INSTVARS, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_OOP, @@ -217,6 +232,7 @@ static kernel_class_info_t kernel_classes[] = { 11, { 'A','s','s','o','c','i','a','t','i','o','n' }, 0, + 0, MOO_ASSOCIATION_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP, @@ -225,6 +241,7 @@ static kernel_class_info_t kernel_classes[] = { 13, { 'M','e','t','h','o','d','C','o','n','t','e','x','t' }, MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED, + 0, MOO_CONTEXT_NAMED_INSTVARS, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_OOP, @@ -233,6 +250,7 @@ static kernel_class_info_t kernel_classes[] = { 12, { 'B','l','o','c','k','C','o','n','t','e','x','t' }, MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED, + 0, MOO_CONTEXT_NAMED_INSTVARS, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_OOP, @@ -241,6 +259,7 @@ static kernel_class_info_t kernel_classes[] = { 7, { 'P','r','o','c','e','s','s' }, MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED, + 0, MOO_PROCESS_NAMED_INSTVARS, MOO_CLASS_SPEC_FLAG_INDEXED, MOO_OBJ_TYPE_OOP, @@ -249,6 +268,7 @@ static kernel_class_info_t kernel_classes[] = { 9, { 'S','e','m','a','p','h','o','r','e' }, 0, + 0, MOO_SEMAPHORE_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP, @@ -257,6 +277,7 @@ static kernel_class_info_t kernel_classes[] = { 14, { 'S','e','m','a','p','h','o','r','e','G','r','o','u','p' }, 0, + 0, MOO_SEMAPHORE_GROUP_NAMED_INSTVARS, 0, MOO_OBJ_TYPE_OOP, @@ -264,17 +285,19 @@ static kernel_class_info_t kernel_classes[] = { 16, { 'P','r','o','c','e','s','s','S','c','h','e','d','u','l','e','r' }, - MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED, - MOO_PROCESS_SCHEDULER_NAMED_INSTVARS, - 0, - MOO_OBJ_TYPE_OOP, - MOO_OFFSETOF(moo_t, _process_scheduler) }, + MOO_CLASS_SELFSPEC_FLAG_FINAL | MOO_CLASS_SELFSPEC_FLAG_LIMITED, + 0, + MOO_PROCESS_SCHEDULER_NAMED_INSTVARS, + 0, + MOO_OBJ_TYPE_OOP, + MOO_OFFSETOF(moo_t, _process_scheduler) }, { 5, { 'E','r','r','o','r' }, MOO_CLASS_SELFSPEC_FLAG_LIMITED, 0, 0, + 0, MOO_OBJ_TYPE_OOP, MOO_OFFSETOF(moo_t, _error_class) }, @@ -283,6 +306,7 @@ static kernel_class_info_t kernel_classes[] = 0, 0, 0, + 0, MOO_OBJ_TYPE_OOP, MOO_OFFSETOF(moo_t, _true_class) }, @@ -291,6 +315,7 @@ static kernel_class_info_t kernel_classes[] = 0, 0, 0, + 0, MOO_OBJ_TYPE_OOP, MOO_OFFSETOF(moo_t, _false_class) }, @@ -302,6 +327,7 @@ static kernel_class_info_t kernel_classes[] = MOO_CLASS_SELFSPEC_FLAG_LIMITED, 0, 0, + 0, MOO_OBJ_TYPE_OOP, MOO_OFFSETOF(moo_t, _character) }, @@ -310,6 +336,7 @@ static kernel_class_info_t kernel_classes[] = MOO_CLASS_SELFSPEC_FLAG_LIMITED, 0, 0, + 0, MOO_OBJ_TYPE_OOP, MOO_OFFSETOF(moo_t, _small_integer) }, @@ -317,6 +344,7 @@ static kernel_class_info_t kernel_classes[] = { 'L','a','r','g','e','P','o','s','i','t','i','v','e','I','n','t','e','g','e','r' }, 0, 0, + 0, MOO_CLASS_SPEC_FLAG_INDEXED | MOO_CLASS_SPEC_FLAG_IMMUTABLE, MOO_OBJ_TYPE_LIWORD, MOO_OFFSETOF(moo_t, _large_positive_integer) }, @@ -325,6 +353,7 @@ static kernel_class_info_t kernel_classes[] = { 'L','a','r','g','e','N','e','g','a','t','i','v','e','I','n','t','e','g','e','r' }, 0, 0, + 0, MOO_CLASS_SPEC_FLAG_INDEXED | MOO_CLASS_SPEC_FLAG_IMMUTABLE, MOO_OBJ_TYPE_LIWORD, MOO_OFFSETOF(moo_t, _large_negative_integer) }, @@ -334,12 +363,14 @@ static kernel_class_info_t kernel_classes[] = 0, 0, 0, + 0, MOO_OBJ_TYPE_OOP, MOO_OFFSETOF(moo_t, _small_pointer) }, { 6, { 'S','y','s','t','e','m' }, 0, + 1, /* asyncsg */ 0, 0, MOO_OBJ_TYPE_OOP, @@ -386,7 +417,8 @@ static int ignite_1 (moo_t* moo) * which are actually class variables. * -------------------------------------------------------------- */ moo->_class = alloc_kernel_class ( - moo, kernel_classes[KCI_CLASS].class_flags, 0, + moo, kernel_classes[KCI_CLASS].class_flags, + kernel_classes[KCI_CLASS].class_num_classvars, MOO_CLASS_SPEC_MAKE (kernel_classes[KCI_CLASS].class_spec_named_instvars, kernel_classes[KCI_CLASS].class_spec_flags, kernel_classes[KCI_CLASS].class_spec_indexed_type)); @@ -402,7 +434,8 @@ static int ignite_1 (moo_t* moo) if (i == KCI_CLASS) continue; /* skip Class as it's created above */ tmp = alloc_kernel_class ( - moo, kernel_classes[i].class_flags, 0, + moo, kernel_classes[i].class_flags, + kernel_classes[i].class_num_classvars, MOO_CLASS_SPEC_MAKE (kernel_classes[i].class_spec_named_instvars, kernel_classes[i].class_spec_flags, kernel_classes[i].class_spec_indexed_type)); diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 035d6fe..abb2071 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -754,7 +754,7 @@ typedef struct moo_process_t* moo_oop_process_t; typedef struct moo_semaphore_t moo_semaphore_t; typedef struct moo_semaphore_t* moo_oop_semaphore_t; -#define MOO_SEMAPHORE_GROUP_NAMED_INSTVARS 6 +#define MOO_SEMAPHORE_GROUP_NAMED_INSTVARS 7 typedef struct moo_semaphore_group_t moo_semaphore_group_t; typedef struct moo_semaphore_group_t* moo_oop_semaphore_group_t; @@ -846,6 +846,8 @@ struct moo_semaphore_group_t moo_oop_semaphore_t first; moo_oop_semaphore_t last; } sems[2]; /* sems[0] - unsignaled semaphores, sems[1] - signaled semaphores */ + + moo_oop_t sem_io_count; }; #define MOO_PROCESS_SCHEDULER_NAMED_INSTVARS 9