[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