[Pvfs2-cvs] commit by slang in pvfs2/src/common/misc: state-machine-fns.c state-machine.h

CVS commit program cvs at parl.clemson.edu
Tue Apr 1 18:25:07 EST 2008


Update of /projects/cvsroot/pvfs2/src/common/misc
In directory parlweb1:/tmp/cvs-serv26625/src/common/misc

Modified Files:
      Tag: pvfs-2-7-branch
	state-machine-fns.c state-machine.h 
Log Message:
merge a bunch of fixes made to HEAD since 2.7.0.


Index: state-machine-fns.c
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/common/misc/state-machine-fns.c,v
diff -p -u -r1.5 -r1.5.2.1
--- state-machine-fns.c	30 Aug 2007 00:13:43 -0000	1.5
+++ state-machine-fns.c	1 Apr 2008 23:25:07 -0000	1.5.2.1
@@ -48,7 +48,7 @@ struct PINT_frame_s
 static struct PINT_state_s *PINT_pop_state(struct PINT_smcb *);
 static void PINT_push_state(struct PINT_smcb *, struct PINT_state_s *);
 static struct PINT_state_s *PINT_sm_task_map(struct PINT_smcb *smcb, int task_id);
-static void PINT_sm_start_child_frames(struct PINT_smcb *smcb);
+static void PINT_sm_start_child_frames(struct PINT_smcb *smcb, int* children_started);
 
 /* Function: PINT_state_machine_halt(void)
    Params: None
@@ -70,30 +70,38 @@ int PINT_state_machine_halt(void)
  */
 int PINT_state_machine_terminate(struct PINT_smcb *smcb, job_status_s *r)
 {
-    struct PINT_frame_s *current_frame;
+    struct PINT_frame_s *my_frame, *f;
     job_id_t id;
 
     /* notify parent */
     if (smcb->parent_smcb)
     {
-        assert(smcb->parent_smcb->children_running > 0);
-
-        current_frame = qlist_entry(
-            &smcb->frames.next, struct PINT_frame_s, link);
-        current_frame->error = r->error_code;
+        gossip_debug(GOSSIP_STATE_MACHINE_DEBUG, 
+                     "[SM Terminating Child]: (%p) (error_code: %d)\n",
+                     smcb,
+                     /* skip pvfs2_ */
+                     (int32_t)r->error_code);
+         assert(smcb->parent_smcb->children_running > 0);
+
+         my_frame = qlist_entry(
+            smcb->frames.next, struct PINT_frame_s, link);
+         qlist_for_each_entry(f, &smcb->parent_smcb->frames, link)
+         {
+             if(my_frame->frame == f->frame)
+             {
+                 f->error = r->error_code;
+                 break;
+             }
+         }
 
-        if (--smcb->parent_smcb->children_running > 0)
-        {
-            /* SM is still deferred */
-            return SM_ACTION_DEFERRED;
-        }
-        else
+        if (--smcb->parent_smcb->children_running <= 0)
         {
             /* no more child state machines running, so we can
              * start up the parent state machine again
              */
             job_null(0, smcb->parent_smcb, 0, r, &id, smcb->context);
         }
+        return SM_ACTION_DEFERRED;
     }
     /* call state machine completion function */
     if (smcb->terminate_fn)
@@ -117,6 +125,7 @@ PINT_sm_action PINT_state_machine_invoke
     PINT_sm_action retval;
     const char * state_name;
     const char * machine_name;
+    int children_started = 0;
 
     if (!(smcb) || !(smcb->current_state) ||
             !(smcb->current_state->flag == SM_RUN ||
@@ -127,10 +136,6 @@ PINT_sm_action PINT_state_machine_invoke
         return SM_ERROR;
     }
 
-    /* print pre-call debugging info */
-    gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
-            "SM invoke smcb %p op %d\n",smcb,(smcb)->op);
-
     state_name = PINT_state_machine_current_state_name(smcb);
     machine_name = PINT_state_machine_current_machine_name(smcb);
 
@@ -148,17 +153,10 @@ PINT_sm_action PINT_state_machine_invoke
     switch (retval)
     {
     case SM_ACTION_TERMINATE :
-            gossip_debug(GOSSIP_STATE_MACHINE_DEBUG, 
-                    "SM Terminates (%p)\n", smcb);
             smcb->op_terminate = 1;
             break;
     case SM_ACTION_COMPLETE :
-            gossip_debug(GOSSIP_STATE_MACHINE_DEBUG, 
-                    "SM Returns Complete (%p)\n", smcb);
-            break;
     case SM_ACTION_DEFERRED :
-            gossip_debug(GOSSIP_STATE_MACHINE_DEBUG, 
-                    "SM Returns Deferred (%p)\n", smcb);
             break;
     default :
             /* error */
@@ -169,7 +167,7 @@ PINT_sm_action PINT_state_machine_invoke
 
     /* print post-call debugging info */
     gossip_debug(GOSSIP_STATE_MACHINE_DEBUG, 
-                 "[SM Exiting]: (%p) %s:%s (error code: %d), (sm action: %s)\n",
+                 "[SM Exiting]: (%p) %s:%s (error code: %d), (action: %s)\n",
                  smcb,
                  /* skip pvfs2_ */
                  machine_name,
@@ -180,11 +178,13 @@ PINT_sm_action PINT_state_machine_invoke
     if (retval == SM_ACTION_COMPLETE && smcb->current_state->flag == SM_PJMP)
     {
         /* start child SMs */
-        PINT_sm_start_child_frames(smcb);
-        gossip_debug(GOSSIP_STATE_MACHINE_DEBUG, 
-                "SM (%p) started %d child frames\n",
-                smcb, smcb->children_running);
-        if (smcb->children_running > 0)
+        PINT_sm_start_child_frames(smcb, &children_started);
+        /* if any children were started, then we return DEFERRED (even
+         * though they may have all completed immediately).  The last child
+         * issues a job_null that will drive progress from here and we don't
+         * want to cause a double transition.
+         */
+        if (children_started > 0)
             retval = SM_ACTION_DEFERRED;
         else
             retval = SM_ACTION_COMPLETE;
@@ -205,19 +205,25 @@ PINT_sm_action PINT_state_machine_start(
 {
     PINT_sm_action ret;
 
+    /* set the state machine to being completed immediately.  We
+     * unset this bit once the state machine is deferred.
+     */
+    smcb->immediate = 1;
+
     /* run the current state action function */
     ret = PINT_state_machine_invoke(smcb, r);
     if (ret == SM_ACTION_COMPLETE || ret == SM_ACTION_TERMINATE)
     {
         /* keep running until state machine deferrs or terminates */
-        ret = PINT_state_machine_next(smcb, r);
-        
-        /* note that if ret == SM_ACTION_TERMINATE, we _don't_ call
-         * PINT_state_machine_terminate here because that adds the smcb
-         * to the completion list.  We don't want to do that on immediate
-         * completion
-         */
+        ret = PINT_state_machine_continue(smcb, r);
+    }
+
+    if(ret == SM_ACTION_DEFERRED)
+    {
+        /* this state machine isn't completing immediately */
+        smcb->immediate = 0;
     }
+
     return ret;
 }
 
@@ -239,8 +245,6 @@ PINT_sm_action PINT_state_machine_next(s
         gossip_err("SM next called on invald smcb\n");
         return -1;
     }
-    gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
-            "SM next smcb %p op %d\n",smcb,(smcb)->op);
     /* loop while invoke of new state returns COMPLETED */
     do {
         /* loop while returning from nested SM */
@@ -254,12 +258,12 @@ PINT_sm_action PINT_state_machine_next(s
                 return -1;
             }
             transtbl = smcb->current_state->trtbl;
-    
-	    /* for each entry in the transition table there is a return
-	    * code followed by a next state pointer to the new state.
-	    * This loops through each entry, checking for a match on the
-	    * return address, and then sets the new current_state and calls
-	    * the new state action function */
+
+            /* for each entry in the transition table there is a return
+             * code followed by a next state pointer to the new state.
+             * This loops through each entry, checking for a match on the
+             * return address, and then sets the new current_state and calls
+             * the new state action function */
             for (i = 0; transtbl[i].return_value != DEFAULT_ERROR; i++)
             {
                 if (transtbl[i].return_value == r->error_code)
@@ -293,6 +297,13 @@ PINT_sm_action PINT_state_machine_next(s
                  * and we'll continue from the state returned to
                  */
 	        smcb->current_state = PINT_pop_state(smcb);
+                if(!smcb->current_state ||
+                   smcb->current_state->trtbl[0].flag == SM_TERM)
+                {
+                    /* assume nested state machine was invoked without
+                     * a parent */
+                    return SM_ACTION_TERMINATE;
+                }
 	    }
         } while (transtbl[i].flag == SM_RETURN);
         smcb->current_state = transtbl[i].next_state;
@@ -346,6 +357,8 @@ int PINT_state_machine_locate(struct PIN
 {
     struct PINT_state_s *current_tmp;
     struct PINT_state_machine_s *op_sm;
+    const char *state_name;
+    const char *machine_name;
 
     /* check for valid inputs */
     if (!smcb || smcb->op < 0 || !smcb->op_get_state_machine)
@@ -354,7 +367,7 @@ int PINT_state_machine_locate(struct PIN
 	return -PVFS_EINVAL;
     }
     gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
-            "SM locate smcb %p op %d\n",smcb,(smcb)->op);
+            "[SM Locating]: (%p) op-id: %d\n",smcb,(smcb)->op);
     /* this is a the usage dependant routine to look up the SM */
     op_sm = (*smcb->op_get_state_machine)(smcb->op);
     if (op_sm != NULL)
@@ -370,6 +383,14 @@ int PINT_state_machine_locate(struct PIN
                            current_tmp->action.nested)->first_state;
 	}
         smcb->current_state = current_tmp;
+
+        state_name = PINT_state_machine_current_state_name(smcb);
+        machine_name = PINT_state_machine_current_machine_name(smcb);
+
+        gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
+                     "[SM Locating]: (%p) located: %s:%s\n",
+                     smcb, machine_name, state_name);
+
 	return 1; /* indicates successful locate */
     }
     gossip_err("State machine not found for operation %d\n",smcb->op);
@@ -384,12 +405,15 @@ int PINT_state_machine_locate(struct PIN
  */
 int PINT_smcb_set_op(struct PINT_smcb *smcb, int op)
 {
-    gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
-            "SM set op smcb %p op %d\n",smcb,op);
     smcb->op = op;
     return PINT_state_machine_locate(smcb);
 }
 
+int PINT_smcb_immediate_completion(struct PINT_smcb *smcb)
+{
+    return smcb->immediate;
+}
+
 /* Function: PINT_smcb_op
    Params: pointer to an smcb pointer
    Returns: op (int)
@@ -490,8 +514,6 @@ int PINT_smcb_alloc(
     {
         return -PVFS_ENOMEM;
     }
-    gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
-            "SM allocate smcb %p op %d\n",*smcb,op);
     /* zero out all members */
     memset(*smcb, 0, sizeof(struct PINT_smcb));
 
@@ -531,8 +553,6 @@ void PINT_smcb_free(struct PINT_smcb *sm
 {
     struct PINT_frame_s *frame_entry, *tmp;
     assert(smcb);
-    gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
-             "SM free smcb %p op %d\n", smcb, smcb->op);
     qlist_for_each_entry_safe(frame_entry, tmp, &smcb->frames, link)
     {
         if (frame_entry->frame && frame_entry->task_id == 0)
@@ -555,8 +575,10 @@ void PINT_smcb_free(struct PINT_smcb *sm
  */
 static struct PINT_state_s *PINT_pop_state(struct PINT_smcb *smcb)
 {
-    assert(smcb->stackptr > 0);
-
+    if(smcb->stackptr == 0)
+    {
+        return NULL;
+    }
     return smcb->state_stack[--smcb->stackptr];
 }
 
@@ -599,12 +621,10 @@ void *PINT_sm_frame(struct PINT_smcb *sm
         next = smcb->frames.next;
         while(i < index)
         {
+            i++;
             next = next->next;
         }
         frame_entry = qlist_entry(next, struct PINT_frame_s, link);
-        gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
-                     "FRAME GET smcb %p index %d -> frame: %p\n",
-                     smcb, index, frame_entry->frame);
         return frame_entry->frame;
     }
 }
@@ -618,9 +638,8 @@ int PINT_sm_push_frame(struct PINT_smcb 
 {
     struct PINT_frame_s *newframe;
     gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
-                 "PUSH FRAME %p onto smcb %p\n",
-                 frame_p, smcb);
-
+                 "[SM Frame PUSH]: (%p) frame: %p\n",
+                 smcb, frame_p);
     newframe = malloc(sizeof(struct PINT_frame_s));
     if(!newframe)
     {
@@ -629,15 +648,22 @@ int PINT_sm_push_frame(struct PINT_smcb 
     newframe->task_id = task_id;
     newframe->frame = frame_p;
     qlist_add(&newframe->link, &smcb->frames);
+    smcb->frame_count++;
     return 0;
 }
 
 /* Function: PINT_sm_pop_frame
- * Params: pointer to an smcb pointer
+ * Params: smcb - pointer to an smcb pointer
+ *         task_id - the task id of this frame
+ *         error_code - the frame's error if there was one.
+ *         remaining - count of remaining frames on the smcb.
  * Returns: frame pointer
  * Synopsis: pops a frame pointer from the frame_stack and returns it
  */
-void *PINT_sm_pop_frame(struct PINT_smcb *smcb, int *error_code)
+void *PINT_sm_pop_frame(struct PINT_smcb *smcb, 
+                        int *task_id,
+                        int *error_code,
+                        int *remaining)
 {
     struct PINT_frame_s *frame_entry;
     void *frame;
@@ -647,17 +673,24 @@ void *PINT_sm_pop_frame(struct PINT_smcb
         return NULL;
     }
 
-    frame_entry = qlist_entry(&smcb->frames.next, struct PINT_frame_s, link);
+    frame_entry = qlist_entry(smcb->frames.next, struct PINT_frame_s, link);
     qlist_del(smcb->frames.next);
+    smcb->frame_count--;
+
+    if(remaining)
+    {
+        *remaining = smcb->frame_count;
+    }
 
     frame = frame_entry->frame;
     *error_code = frame_entry->error;
+    *task_id = frame_entry->task_id;
 
     free(frame_entry);
 
     gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
-            "POP FRAME %p from smcb %p\n",
-            frame, smcb);
+            "[SM Frame POP]: (%p) frame: %p\n",
+            smcb, frame);
     return frame;
 }
 
@@ -688,31 +721,65 @@ static int child_sm_frame_terminate(stru
 }
 
 /* Function: PINT_sm_start_child_frames
- * Params: pointer to an smcb pointer
+ * Params: pointer to an smcb pointer and pointer to count of children
+ *      started
  * Returns: number of children started
  * Synopsis: This starts all the enw child SMs based on the frame_stack
  *      This is called by the invoke function above which expects the
  *      number of children to be returned to decide if the state is
  *      deferred or not.
  */
-static void PINT_sm_start_child_frames(struct PINT_smcb *smcb)
+static void PINT_sm_start_child_frames(struct PINT_smcb *smcb, int* children_started)
 {
     int retval;
     struct PINT_smcb *new_sm;
     struct PINT_frame_s *frame_entry;
     job_status_s r;
+    struct qlist_head *f;
 
     assert(smcb);
 
-    qlist_for_each_entry(frame_entry, &smcb->frames, link)
+    memset(&r, 0, sizeof(job_status_s));
+
+    *children_started = 0;
+
+    /* Iterate once up front to determine how many children we are going to
+     * run.  This has to be set before starting any children, otherwise if
+     * the first one immediately completes it will mistakenly believe it is
+     * the last one and signal the parent.
+     */
+    qlist_for_each(f, &smcb->frames)
     {
+        /* skip the last since its the parent frame */
+        if(f->next == &smcb->frames)
+        {
+            break;
+        }
+        /* increment parent's counter */
+        smcb->children_running++;
+    }
+
+    /* let the caller know how many children are being started; it won't be
+     * able to tell from the running_count because they may all immediately
+     * complete before we leave this function.
+     */
+    *children_started = smcb->children_running;
+
+    qlist_for_each(f, &smcb->frames)
+    {
+        /* skip the last since its the parent frame */
+        if(f->next == &smcb->frames)
+        {
+            break;
+        }
+
+        frame_entry = qlist_entry(f, struct PINT_frame_s, link);
+
         /* allocate smcb */
         PINT_smcb_alloc(&new_sm, smcb->op, 0, NULL,
                 child_sm_frame_terminate, smcb->context);
         /* set parent smcb pointer */
         new_sm->parent_smcb = smcb;
-        /* increment parent's counter */
-        smcb->children_running++;
         /* assign frame */
         PINT_sm_push_frame(new_sm, frame_entry->task_id, frame_entry->frame);
         /* locate SM to run */

Index: state-machine.h
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/common/misc/state-machine.h,v
diff -p -u -r1.16 -r1.16.2.1
--- state-machine.h	30 Aug 2007 00:13:43 -0000	1.16
+++ state-machine.h	1 Apr 2008 23:25:07 -0000	1.16.2.1
@@ -68,6 +68,7 @@ typedef struct PINT_smcb
     struct PINT_state_s *state_stack[PINT_STATE_STACK_SIZE];
 
     struct qlist_head frames;
+    int frame_count;
 
     /* usage specific routinet to look up SM from OP */
     struct PINT_state_machine_s *(*op_get_state_machine)(int);
@@ -83,6 +84,7 @@ typedef struct PINT_smcb
     job_context_id context; /* job context when waiting for children */
     int (*terminate_fn)(struct PINT_smcb *, job_status_s *);
     void *user_ptr; /* external user pointer */
+    int immediate; /* specifies immediate completion of the state machine */
 } PINT_smcb;
 
 #define PINT_SET_OP_COMPLETE do{PINT_smcb_set_complete(smcb);} while (0)
@@ -152,14 +154,6 @@ enum {
 #define SM_STATE_RETURN -1
 #define SM_NESTED_STATE 1
 
-#define SM_NONE   0
-#define SM_NEXT   1
-#define SM_RETURN 2
-#define SM_EXTERN 3
-#define SM_NESTED 5
-#define SM_JUMP   6
-#define SM_TERMINATE 7
-
 /* Prototypes for functions provided by user */
 int PINT_state_machine_complete(void *);
 
@@ -167,11 +161,11 @@ int PINT_state_machine_complete(void *);
  * We assume the first 6 characters of every state machine name are "pvfs2_".
  */
 #define PINT_state_machine_current_machine_name(smcb) \
-    (((smcb)->current_state->parent_machine->name) + 6)
+    ((smcb)->current_state ? (((smcb)->current_state->parent_machine->name) + 6) : "UNKNOWN")
 
 /* This macro returns the current state invoked */
 #define PINT_state_machine_current_state_name(smcb) \
-    ((smcb)->current_state->state_name)
+    ((smcb)->current_state ? ((smcb)->current_state->state_name) : "UNKNOWN")
 
 /* Prototypes for functions defined in by state machine code */
 int PINT_state_machine_halt(void);
@@ -184,6 +178,7 @@ PINT_sm_action PINT_state_machine_contin
 int PINT_state_machine_locate(struct PINT_smcb *) __attribute__((used));
 int PINT_smcb_set_op(struct PINT_smcb *smcb, int op);
 int PINT_smcb_op(struct PINT_smcb *smcb);
+int PINT_smcb_immediate_completion(struct PINT_smcb *smcb);
 void PINT_smcb_set_complete(struct PINT_smcb *smcb);
 int PINT_smcb_invalid_op(struct PINT_smcb *smcb);
 int PINT_smcb_complete(struct PINT_smcb *smcb);
@@ -196,9 +191,10 @@ int PINT_smcb_alloc(struct PINT_smcb **,
 void PINT_smcb_free(struct PINT_smcb *);
 void *PINT_sm_frame(struct PINT_smcb *, int);
 int PINT_sm_push_frame(struct PINT_smcb *smcb, int task_id, void *frame_p);
-void *PINT_sm_pop_frame(struct PINT_smcb *smcb, int *error_code);
-
-int PINT_sm_pop_error(PINT_smcb *smcb, PVFS_error ret);
+void *PINT_sm_pop_frame(struct PINT_smcb *smcb,
+                        int *task_id,
+                        int *error_code,
+                        int *remaining);
 
 /* This macro is used in calls to PINT_sm_fram() */
 #define PINT_FRAME_CURRENT 0



More information about the Pvfs2-cvs mailing list