[Pvfs2-cvs] commit by walt in pvfs2-1/src/common/misc:
state-machine-fns.c state-machine-values.h state-machine.h
CVS commit program
cvs at parl.clemson.edu
Tue Aug 1 11:52:01 EDT 2006
Update of /projects/cvsroot/pvfs2-1/src/common/misc
In directory parlweb1:/tmp/cvs-serv30331/src/common/misc
Modified Files:
Tag: WALT3
state-machine-fns.c state-machine-values.h state-machine.h
Log Message:
updated term code, SM union remval and statecomp update for pjmp states
compiles clean, beginning test
Index: state-machine-fns.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/Attic/state-machine-fns.c,v
diff -p -u -r1.1.2.8 -r1.1.2.9
--- state-machine-fns.c 20 Jul 2006 23:08:32 -0000 1.1.2.8
+++ state-machine-fns.c 1 Aug 2006 15:52:01 -0000 1.1.2.9
@@ -46,12 +46,43 @@ int PINT_state_machine_halt(void)
return 0;
}
+/* Function: PINT_state_machine_terminate
+ Params: smcb, job status
+ Returns: 0 on sucess, otherwise error
+ Synopsis: This function cleans up and terminates a SM
+ in some cases we may need to keep the SM alive until
+ its children terminate or something - in which case we
+ will post the relevant job here.
+ */
+int PINT_state_machine_terminate(struct PINT_smcb *smcb, job_status_s *r)
+{
+ /* notify parent */
+ if (smcb->parent_smcb)
+ {
+ job_id_t id;
+ /* acquire lock here */
+ if (--smcb->parent_smcb->children_running == 0)
+ {
+ /* wake up parent, through job interface */
+ job_null(0, smcb, 0, r, &id, smcb->context);
+ }
+ /* release lock here */
+ }
+ /* call state machine completion function */
+ if (smcb->terminate_fn)
+ {
+ (*smcb->terminate_fn)(smcb, r);
+ }
+ return 0;
+}
+
/* Function: PINT_state_machine_invoke
- Params:
- Returns:
- Synopsis: Currently undocumented! Why is this here? appears
- only potential use is in the function above, where it
- it isn't even used.
+ Params: smcb pointer and job status pointer
+ Returns: return value of state action
+ Synopsis: runs the current state action, produces debugging
+ output if needed, checls return value and takes action
+ if needed (sets op_terminate if SM_ACTION_TERMINATED is
+ returned)
*/
int PINT_state_machine_invoke(struct PINT_smcb *smcb, job_status_s *r)
{
@@ -59,11 +90,15 @@ int PINT_state_machine_invoke(struct PIN
const char * state_name;
const char * machine_name;
- if (!smcb || !smcb->current_state || !smcb->current_state->state_action)
+ if (!smcb || !smcb->current_state ||
+ !smcb->current_state->flag == SM_RUN ||
+ !smcb->current_state->action.func)
{
gossip_err("SM invoke called in invalid smcb\n");
return -1;
}
+
+ /* print pre-call debugging info */
gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
"SM invoke smcb %p op %d\n",smcb,(smcb)->op);
@@ -77,9 +112,11 @@ int PINT_state_machine_invoke(struct PIN
machine_name,
state_name,
(int32_t)r->status_user_tag);
-
- retval = (smcb->current_state->state_action)(smcb,r);
+
+ /* call state action function */
+ retval = (smcb->current_state->action.func)(smcb,r);
+ /* print post-call debugging info */
gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
"[SM Exiting]: (%p) %s:%s (error code: %d)\n",
smcb,
@@ -88,40 +125,59 @@ int PINT_state_machine_invoke(struct PIN
state_name,
r->error_code);
- /* process return value */
+ /* process return code */
switch (retval)
{
+ case SM_ACTION_TERMINATE :
+ {
+ smcb->op_terminate = 1;
+ }
case SM_ACTION_COMPLETE :
case SM_ACTION_DEFERRED :
- return retval;
+ {
+ return retval;
+ }
default :
- /* error */
- break;
+ {
+ /* error */
+ gossip_err("SM returned invalid return code %d\n", retval);
+ break;
+ }
}
return retval;
}
+/* Function: PINT_state_machine_next()
+ Params: smcb pointer and job status pointer
+ Returns: return value of last state action
+ Synopsis: runs the state action pointed to by the
+ current state, then continues to run the SM
+ as long asreturn code is SM_ACTION_COMPLETE
+ */
+
int PINT_state_machine_start(struct PINT_smcb *smcb, job_status_s *r)
{
int ret;
+ /* run the current state action function */
ret = PINT_state_machine_invoke(smcb, r);
- if (ret == SM_ACTION_COMPLETE)
+ if (ret == SM_ACTION_COMPLETE || ret == SM_ACTION_TERMINATE)
+ /* keep running until state machine deferrs or terminates */
ret = PINT_state_machine_next(smcb, r);
return ret;
}
/* Function: PINT_state_machine_next()
- Params:
- Returns: return value of state action
-
+ Params: smcb pointer and job status pointer
+ Returns: return value of last state action
Synopsis: Runs through a list of return values to find the next function to
call. Calls that function. If that function returned COMPLETED loop
and repeat.
*/
int PINT_state_machine_next(struct PINT_smcb *smcb, job_status_s *r)
{
- union PINT_state_array_values *loc; /* temp pointer into state memory */
+ struct PINT_state_s *loc; /* temp pointer into state memory */
+ struct PINT_tran_tbl_s *tloc;
int ret; /* holes state action return code */
if (!smcb && !smcb->current_state)
@@ -138,50 +194,66 @@ int PINT_state_machine_next(struct PINT_
/* skip over the current state action to
* get to the return code list
*/
- loc = smcb->current_state + 1;
+ loc = smcb->current_state;
+ tloc = loc->trtbl;
/* for each entry in the state machine 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 */
- while (loc->return_value != r->error_code &&
- loc->return_value != DEFAULT_ERROR)
+ while (tloc->return_value != r->error_code &&
+ tloc->return_value != DEFAULT_ERROR)
{
/* each entry has a return value followed by a next state
* pointer, so we increment by two.
*/
- loc += 2;
+ tloc += 1;
}
/* skip over the return code to get to the pointer for the
* next state
*/
- loc += 1;
+ /*loc += 1;*/
- /* its not legal to actually reach a termination point; preceding
- * function should have completed state machine.
+ /* we expect the last state action function to return
+ * SM_ACTION_TERMINATE which sets the smcb->op_terminate
+ * flag. ALSO the state machine much direct the next state
+ * to be terminate, which sets loc->flag to SM_TERMINATE.
+ * We'll terminate for EITHER, but print an error if not
+ * both.
*/
- if(loc->flag == SM_TERMINATE)
+ if(tloc->flag == SM_TERM || smcb->op_terminate)
{
- gossip_err("Error: state machine using an"
- " invalid termination path.\n");
- return(-PVFS_EINVAL);
+ if (!(tloc->flag == SM_TERM))
+ {
+ gossip_lerr("Error: state machine reached terminate"
+ " without returning SM_ACTION_TERMINATE\n");
+ }
+ {
+ if (!smcb->op_terminate)
+ gossip_lerr("Error: state machine returned"
+ " SM_ACTION_TERMINATE but didn't reach terminate\n");
+ }
+ /* process terminating SM */
+ PINT_state_machine_terminate(smcb, r);
+
+ return SM_ACTION_TERMINATE;
}
/* Update the server_op struct to reflect the new location
* see if the selected return value is a STATE_RETURN */
- if (loc->flag == SM_RETURN)
+ if (tloc->flag == SM_RETURN)
{
smcb->current_state = PINT_pop_state(smcb);
/* skip state flags */
- smcb->current_state += 1;
+ /*smcb->current_state += 1;*/
}
- } while (loc->flag == SM_RETURN);
+ } while (tloc->flag == SM_RETURN);
- smcb->current_state = loc->next_state;
+ smcb->current_state = tloc->next_state;
/* skip state name and parent SM ref */
- smcb->current_state += 2;
+ /*smcb->current_state += 2;*/
/* To do nested states, we check to see if the next state is
* a nested state machine, and if so we push the return state
@@ -191,23 +263,23 @@ int PINT_state_machine_next(struct PINT_
PINT_push_state(smcb, smcb->current_state);
/* skip state flag; now we point to the SM */
- smcb->current_state += 1;
+ /*smcb->current_state += 1;*/
smcb->current_state =
- smcb->current_state->nested_machine->state_machine;
+ smcb->current_state->action.nested->state_machine;
/* skip state name a parent SM ref */
- smcb->current_state += 2;
+ /*smcb->current_state += 2;*/
}
/* skip over the flag so that we point to the function for the next
* state. then call it.
*/
- smcb->current_state += 1;
+ /*smcb->current_state += 1;*/
/* runs state_action and returns the return code */
ret = PINT_state_machine_invoke(smcb, r);
- } while (ret == SM_ACTION_COMPLETE);
+ } while (ret == SM_ACTION_COMPLETE || ret == SM_ACTION_TERMINATE);
return ret;
}
@@ -222,14 +294,14 @@ int PINT_state_machine_next(struct PINT_
*/
int PINT_state_machine_locate(struct PINT_smcb *smcb)
{
- union PINT_state_array_values *current_tmp;
+ struct PINT_state_s *current_tmp;
struct PINT_state_machine_s *op_sm;
/* check for valid inputs */
if (!smcb || smcb->op < 0 || !smcb->op_get_state_machine)
{
gossip_err("State machine requested not valid\n");
- return 0;
+ return -PVFS_EINVAL;
}
gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
"SM locate smcb %p op %d\n",smcb,(smcb)->op);
@@ -239,7 +311,7 @@ int PINT_state_machine_locate(struct PIN
{
current_tmp = op_sm->state_machine;
/* skip SM name and parent */
- current_tmp += 2;
+ /*current_tmp += 2;*/
/* handle the case in which the first state points to a nested
* machine, rather than a simple function
*/
@@ -247,18 +319,18 @@ int PINT_state_machine_locate(struct PIN
{
PINT_push_state(smcb, current_tmp);
/* skip state flag */
- current_tmp += 1;
+ /*current_tmp += 1;*/
current_tmp = ((struct PINT_state_machine_s *)
- current_tmp->nested_machine)->state_machine;
+ current_tmp->action.nested)->state_machine;
/* skip SM name and parent */
- current_tmp += 2;
+ /*current_tmp += 2;*/
}
/* this sets a pointer to a "PINT_state_array_values"
* structure, whose state_action member is the function to call.
*/
/* skip state flag */
- smcb->current_state = current_tmp + 1;
+ /*smcb->current_state = current_tmp + 1;*/
return 1; /* indicates successful locate */
}
@@ -293,21 +365,21 @@ int PINT_smcb_op(struct PINT_smcb *smcb)
/* Function: PINT_smcb_set_complete
Params: pointer to an smcb pointer
Returns: nothing
- Synopsis: sets op_complete on existing smcb
+ Synopsis: sets op_terminate on existing smcb
*/
void PINT_smcb_set_complete(struct PINT_smcb *smcb)
{
- smcb->op_complete = 1;
+ smcb->op_terminate = 1;
}
/* Function: PINT_smcb_complete
Params: pointer to an smcb pointer
Returns: op (int)
- Synopsis: returns the op_complete currently set in the smcb
+ Synopsis: returns the op_terminate currently set in the smcb
*/
int PINT_smcb_complete(struct PINT_smcb *smcb)
{
- return smcb->op_complete;
+ return smcb->op_terminate;
}
/* Function: PINT_smcb_set_cancelled
@@ -341,7 +413,9 @@ int PINT_smcb_alloc(
struct PINT_smcb **smcb,
int op,
int frame_size,
- struct PINT_state_machine_s *(*getmach)(int))
+ struct PINT_state_machine_s *(*getmach)(int),
+ int (*term_fn)(struct PINT_smcb *, job_status_s *),
+ job_context_id context_id)
{
*smcb = (struct PINT_smcb *)malloc(sizeof(struct PINT_smcb));
if (!(*smcb))
@@ -350,20 +424,28 @@ int PINT_smcb_alloc(
}
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));
+ /* if frame_size given, allocate a frame */
if (frame_size > 0)
{
(*smcb)->frame_stack[0] = malloc(frame_size);
if (!((*smcb)->frame_stack[0]))
{
+ free(*smcb);
+ *smcb = NULL;
return -PVFS_ENOMEM;
}
+ /* zero out all members */
memset((*smcb)->frame_stack[0], 0, frame_size);
}
(*smcb)->op = op;
(*smcb)->op_get_state_machine = getmach;
+ (*smcb)->terminate_fn = term_fn;
+ (*smcb)->context = context_id;
+ /* if a getmach given, lookup state machine */
if (getmach)
- PINT_state_machine_locate(*smcb);
+ return PINT_state_machine_locate(*smcb);
return 0; /* success */
}
@@ -401,7 +483,7 @@ void PINT_smcb_free(struct PINT_smcb **s
Returns:
Synopsis:
*/
-union PINT_state_array_values *PINT_pop_state(struct PINT_smcb *smcb)
+struct PINT_state_s *PINT_pop_state(struct PINT_smcb *smcb)
{
assert(smcb->stackptr > 0);
@@ -414,7 +496,7 @@ union PINT_state_array_values *PINT_pop_
Synopsis:
*/
void PINT_push_state(struct PINT_smcb *smcb,
- union PINT_state_array_values *p)
+ struct PINT_state_s *p)
{
assert(smcb->stackptr < PINT_STATE_STACK_SIZE);
@@ -480,7 +562,7 @@ void *PINT_sm_pop_frame(struct PINT_smcb
Returns:
Synopsis:
*/
-union PINT_state_array_values *PINT_sm_something(void)
+struct PINT_state_s *PINT_sm_something(void)
{
return NULL;
}
@@ -501,13 +583,18 @@ void PINT_sm_start_child_frames(struct P
for(i = smcb->framebaseptr; i < smcb->framebaseptr; i++)
{
/* allocate smcb */
- PINT_smcb_alloc(&new_sm, smcb->op, 0, NULL);
+ PINT_smcb_alloc(&new_sm, smcb->op, 0, NULL,
+ smcb->terminate_fn, 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, smcb->frame_stack[i]);
/* locate SM to run */
new_sm->current_state = PINT_sm_something();
/* invoke SM */
- PINT_state_machine_invoke(new_sm, r);
+ PINT_state_machine_start(new_sm, r);
}
}
Index: state-machine-values.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/state-machine-values.h,v
diff -p -u -r1.3.36.1 -r1.3.36.2
--- state-machine-values.h 7 Jul 2006 18:09:43 -0000 1.3.36.1
+++ state-machine-values.h 1 Aug 2006 15:52:01 -0000 1.3.36.2
@@ -13,13 +13,17 @@
* they are kept separate from the rest of the code to keep the number of
* includes for the statecomp code down.
*/
-#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
+enum PINT_state_code {
+ SM_NONE = 0,
+ SM_NEXT = 1,
+ SM_RETURN= 2,
+ SM_EXTERN= 3,
+ SM_NESTED= 5,
+ SM_JUMP = 6,
+ SM_TERM = 7,
+ SM_PJMP = 8,
+ SM_RUN = 9
+};
/* these define things like stack size and so forth for the common
* state machine code.
Index: state-machine.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/state-machine.h,v
diff -p -u -r1.12.4.10 -r1.12.4.11
--- state-machine.h 21 Jul 2006 16:28:51 -0000 1.12.4.10
+++ state-machine.h 1 Aug 2006 15:52:01 -0000 1.12.4.11
@@ -48,21 +48,60 @@ typedef struct PINT_smcb
int stackptr;
int framebaseptr;
int framestackptr;
- union PINT_state_array_values *current_state;
- union PINT_state_array_values *state_stack[PINT_STATE_STACK_SIZE];
+ struct PINT_state_s *current_state;
+ struct PINT_state_s *state_stack[PINT_STATE_STACK_SIZE];
void *frame_stack[PINT_FRAME_STACK_SIZE];
/* usage specific routinet to look up SM from OP */
struct PINT_state_machine_s *(*op_get_state_machine)(int);
/* state machine context and control variables */
int op; /* this field externally indicates type of state machine */
PVFS_id_gen_t op_id; /* unique ID for this operation */
- int op_complete; /* indicates operation is complete */
- int op_cancelled; /* indicates operation is cancelled */
+ struct PINT_smcb *parent_smcb; /* points to parent smcb or NULL */
+ int op_terminate; /* indicates SM is ready to terminate */
+ int op_cancelled; /* indicates SM operation was cancelled */
+ int children_running; /* the number of child SMs running */
+ 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 */
} PINT_smcb;
#define PINT_SET_OP_COMPLETE do{PINT_smcb_set_complete(smcb);} while (0)
+struct PINT_state_machine_s
+{
+ const char *name;
+ struct PINT_state_s *state_machine;
+};
+
+struct PINT_state_s
+{
+ const char *state_name;
+ struct PINT_state_machine_s *parent_machine;
+ enum PINT_state_code flag;
+ union
+ {
+ int (*func)(struct PINT_smcb *, job_status_s *);
+ struct PINT_state_machine_s *nested;
+ } action;
+ struct PINT_pjmp_tbl_s *pjtbl;
+ struct PINT_tran_tbl_s *trtbl;
+};
+
+struct PINT_pjmp_tbl_s
+{
+ int return_value;
+ enum PINT_state_code flag;
+ struct PINT_state_machine_s *state_machine;
+};
+
+struct PINT_tran_tbl_s
+{
+ int return_value;
+ enum PINT_state_code flag;
+ struct PINT_state_s *next_state;
+};
+
+#if 0
/* this union defines the possibles values for each word of the
the state machine memory. Properly formed state machine programs
consist of these values in a particular order as documented
@@ -70,14 +109,12 @@ typedef struct PINT_smcb
*/
union PINT_state_array_values
{
- /* these added for debugging? */
const char *state_name;
struct PINT_state_machine_s *parent_machine;
- /* are they still needed?? */
- int (*state_action)(struct PINT_smcb *, job_status_s *);
- int return_value;
int flag;
+ int (*state_action)(struct PINT_smcb *, job_status_s *);
struct PINT_state_machine_s *nested_machine;
+ int return_value;
union PINT_state_array_values *next_state;
};
@@ -87,10 +124,18 @@ struct PINT_state_machine_s
union PINT_state_array_values *state_machine;
};
+struct PINT_state_s
+{
+ const char *state_name;
+ struct PINT_state_machine_s *parent_machine;
+};
+#endif
+
/* All state action functions return this type which controls state
* machine action
*/
typedef enum {
+ SM_ACTION_TERMINATE = 2,
SM_ACTION_COMPLETE = 1,
SM_ACTION_DEFERRED = 0,
SM_ERROR = -1 /* this is a catastrophic error */
@@ -116,11 +161,17 @@ 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 - 2)->parent_machine->name + 6)
+ (((smcb)->current_state->parent_machine->name) + 6)
/* This macro returns the current state invoked */
#define PINT_state_machine_current_state_name(smcb) \
- (((smcb)->current_state - 3)->state_name)
+ ((smcb)->current_state->state_name)
+
+#if 0
+#define PINT_state_machine_current_machine_name(smcb) \
+ (((smcb)->current_state - 2)->parent_machine->name + 6)
+
+#endif
/* Prototypes for functions defined in by state machine code */
int PINT_state_machine_halt(void);
@@ -135,10 +186,12 @@ int PINT_smcb_complete(struct PINT_smcb
void PINT_smcb_set_cancelled(struct PINT_smcb *smcb);
int PINT_smcb_cancelled(struct PINT_smcb *smcb);
int PINT_smcb_alloc(struct PINT_smcb **, int, int,
- struct PINT_state_machine_s *(*getmach)(int));
+ struct PINT_state_machine_s *(*getmach)(int),
+ int (*term_fn)(struct PINT_smcb *, job_status_s *),
+ job_context_id context_id);
void PINT_smcb_free(struct PINT_smcb **);
-union PINT_state_array_values *PINT_pop_state(struct PINT_smcb *);
-void PINT_push_state(struct PINT_smcb *, union PINT_state_array_values *);
+struct PINT_state_s *PINT_pop_state(struct PINT_smcb *);
+void PINT_push_state(struct PINT_smcb *, struct PINT_state_s *);
void *PINT_sm_frame(struct PINT_smcb *, int);
void PINT_sm_push_frame(struct PINT_smcb *smcb, void *frame_p);
void PINT_sm_set_frame(struct PINT_smcb *smcb);
More information about the Pvfs2-cvs
mailing list