T.R | Title | User | Personal Name | Date | Lines |
---|
3073.1 | Which EFN? | DOOBIE::miller | I need 'Deeper Understanding' | Thu Jul 12 1990 17:40 | 11 |
| Which event flag are you using? You know it must reside in cluster 0 so using
lib$get_ef is out.
One way of helping the debug process is to lib$free_ef() the sucker and see
what breaks!
I've been using 7 with no problems and Steve Klein's BTRAP uses 3.
Regards,
== ken miller ==
|
3073.2 | | CREVAS::PROJECTS | | Thu Jul 12 1990 18:41 | 25 |
| RE:
My application uses 7 event flags... the one I am referring to is
event flag 1 and I reserve it using lib$reserve_ef in conjunction
with sys$setimr to place an optional timer request. All works fine
it's just this darn event sequence (mouse activities) that causes
this corruption.
I do know this... in one of the software modules there are two
routines for focus & lost_focus. I remove the calls to them in the UIL
and when I do the focus/lost_focus on the widgets (which is the event
sequence of how to reproduce this bug) the corruption disappears.
I have been thru the routines inside/out and they function properly even
with this minor/major? corruptness.
Where would be a good place to put the lib$free_ef and how might that
affect the sequence of corruption. I think that's what I need to do is
upset the sequence of corruption so as to reproduce different symptoms.
I thought I would be able to set a watch on the event flag itself
but no one has made reference to that even being possible.
Appreciate any help
@@Ken
|
3073.3 | Not an expert, just *been* there... | DOOBIE::miller | I need 'Deeper Understanding' | Thu Jul 12 1990 20:49 | 28 |
| > My application uses 7 event flags... the one I am referring to is
> event flag 1 and I reserve it using lib$reserve_ef in conjunction
> with sys$setimr to place an optional timer request.
Are you checking the status on the lib$reserve_ef() call? The get_ef() doc
says that all the cluster 0 EFN's are *initially* reserved and you must
*free* it before using it (rediculous, if you ask me)...Sure 'nuff, I cycled
through EFN's 1 thru 23 and got "Already Reserved" return status'. In a
nutshell, you just can't tell if one really is available (at least I can't
see it!).
> Where would be a good place to put the lib$free_ef and how might that
> affect the sequence of corruption. I think that's what I need to do is
> upset the sequence of corruption so as to reproduce different symptoms.
What I meant was for you to choose a different EFN (other than 1) and then
in the beginning of your code, lib$free_ef() EFN 1 and see what breaks during
the course of your test! I don't know if it'll really come up with anything,
cause I'm not conviced that lib$reserve_ef() really prevents anyone else
from setting the EFN.
BTW: I'm not pretending that I know too much about this sh*t, I've just been
burned recently with the same kinda problems you're having. Fortunately, I
found an EFN (7) which doesn't seem to cause any visible problems.
Regards,
== ken miller ==
|
3073.4 | who?? | BERN01::SIMONS | Paul Simons 'The European' EIS @EBO | Fri Jul 13 1990 06:10 | 11 |
|
Re .0
> I was wondering how some of you gentleman would approach ...
^^^^^^^
!
"... and Ladies..." next time.
Paul.
|
3073.5 | Pick a number...Pick another one! ;) | GOLLY::MILLER | I need 'Deeper Understanding' | Fri Jul 13 1990 07:12 | 13 |
| <<< Note 3073.2 by CREVAS::PROJECTS >>>
> My application uses 7 event flags... the one I am referring to is
> event flag 1 and I reserve it using lib$reserve_ef in conjunction
I just thought of something else. Somewhere I'm sure I read that EFN
Number 1 is used internally by QIO calls (or something to do with I/O).
I'd definitely try another number!
Regards,
== ken miller ==
|
3073.6 | I've been there | LOWELL::KLEIN | | Fri Jul 13 1990 11:21 | 22 |
| On a different tack.
Modular code must tolerate sharing its event flags with
other portions of the program. There are a limited number of event flags
and eventually they *must* be shared, as the program grows in complexity.
Therefore, any action routine that can be triggered by the setting of an
event flag must contain code to ignore calls made before the associated
operation really has completed.
This is usually done by checking for a non-zero status in the IOSB
associated with the operation. Generalize to the checking of a flag set
in the AST completion routine for the operation. The address of the flag
to set is passed through ASTPRM to the AST routine.
I believe that using the LIB$ routines to reserve, etc, event flags is futile.
The bizarre combination of rules about pre-reserved flags, which flags can
be used in XtAddInput, and the fact that these routines don't work as expected
when called from within a shareable image, make their usefulness questionable.
The rule above has replaced the LIB$*EF convention in all the code I've seen.
-steve-
|
3073.7 | History makes us this way.... | IO::MCCARTNEY | James T. McCartney III - DTN 381-2244 ZK02-2/N24 | Fri Jul 13 1990 12:14 | 23 |
| >>>Are you checking the status on the lib$reserve_ef() call? The get_ef() doc
>>>says that all the cluster 0 EFN's are *initially* reserved and you must
>>>*free* it before using it (rediculous, if you ask me)...Sure 'nuff, I cycled
>>>through EFN's 1 thru 23 and got "Already Reserved" return status'. In a
>>>nutshell, you just can't tell if one really is available (at least I can't
>>>see it!).
The reason for having cluster 0 reserved is simple. The lib$xxx_ef() routines
are relatively new artifacts to VMS. Since there's a large amount of old crusty
code laying about, this seems like a good restriction. Those that can remember
V1.x days know that 64 event flags would be more than anyone could ever need.
Of course there are the days that the DEC-10 people can remember when a network
as large as 100 nodes was totally inconceivable.
What Steve says about event flags in .-1 is true. I believe another way of
stating the same rule is that a properly coded program would work regardless
of which flag is used. The code should actually check that the event did occur.
The rule of thumb that I use is "Would this code work if I used event flag 0?".
I'm not sure that I'd go so far as say that lib$xxx_ef() is obsolete. We use the
lib$xxx_ef() routines on the assumption that a free flag is less "noisy" than
just picking one.
James
|
3073.8 | How new is new? | TLE::LIONEL | Free advice is worth every cent | Fri Jul 13 1990 13:06 | 6 |
| Re: .7
Just for the record, I'm not sure what qualifies to you as "relatively
new", but the LIB$xxx_EF routines were added to VMS V1.5 in 1980 or so.
Steve (LIB$xxx_EF developer)
|
3073.9 | You learn how much there is to learn... | IO::MCCARTNEY | James T. McCartney III - DTN 381-2244 ZK02-2/N24 | Fri Jul 13 1990 14:17 | 9 |
|
RE: .-1
WOW --
I don't recall seeing documentation on these in the 1.x docs. Of course the
set I had at the time was V1 with V1.2 running at the time. Anyway we didn't
start using them really until V3. Thinking back, I guess we went from V1.2 to
V2.4 with minimal doc set updates.
|
3073.10 | | CREVAS::PROJECTS | | Mon Jul 16 1990 13:45 | 26 |
| Sorry about the delay I was away since friday.. here is the source to what I
am doing. I would appreciate any comments, thoughts or opinions.
@@Ken
unsigned long allocate_efn_2_rtn(FUNCPTR ast_rtn, unsigned long *efn)
{
int status;
*efn = 1;
while ( (*efn < 24) && ((status = lib$reserve_ef(efn)) != SS$_NORMAL) )
(*efn)++;
printf ("Reserved efn %d\n", *efn);
/* check that efn was correctly allocated */
if( *efn == 24 )
{
lib$signal (&ICE_EFN_NOT_ALLOCATED);
exit(status);
}
/*
** Declare our event event flags as a special X-event. We do this so
** that we can convert our AST's to X-events.
*/
return (XtAddInput (*efn, 0, ast_rtn, 0));
}
|
3073.11 | Try it the easy way, for starters | LOWELL::KLEIN | | Mon Jul 16 1990 15:30 | 19 |
| Replace all that code with:
#define miscEfn 2 /* use for system service calls */
#define addInputEfn 3 /* use for XtAddInput */
...
XtAddInput (addInputEfn, 0, AddInputCallback, 0);
...
Then, make sure your AddInputCallback routine is prepared to be called
unnecessarily, as was discussed in several of the previous replies to
your note. Use miscEfn for the actual QIOs (or whatever).
I think you are over-engineering your code. It really only takes
one line to do the trick.
-steve-
|
3073.12 | | CREVAS::PROJECTS | | Tue Jul 17 1990 19:30 | 12 |
| Re. 11
It still is not clear what you wanted me to do... about that rule
you mentioned a few replies back. If you could maybe make it sound
more basic I would be able to understand. I am a little thick sometimes.
Anyways I changed that routine that I posted to begin allocating efn's
from event flag 3 and up and that cleared up the problem. I am not
sure if I should blame VMS or not.
Appreciate the help men
@@Ken
|
3073.13 | General example | LOWELL::KLEIN | | Wed Jul 18 1990 15:43 | 132 |
| Here's some code that may help as a general solution. It takes any
QIO (or other AST-based system service) and reschedules the AST
completion routine to be called at non-AST level, between X events.
There are three pieces to this code. First, add the following page of
code to the application, exactly as-is:
----------------------------------------------------------------------
#define miscEfn 2 /* use for system service calls */
#define addInputEfn 3 /* use for XtAddInput */
typedef struct {
unsigned long queueEntryA[2]; /* must be first in struct */
char *mallocP; /* address actually malloc-ed */
void (*routineP)(); /* actual completion routine */
Opaque closure; /* completion routine closure */
} AddInputRec;
/* Relative interlocked queue of pending AddInputRec's */
static _align(quadword) unsigned long addInputQueueHeaderA[2];
/* AddInputCallback is called by the Xt toolkit whenever it is legal to
* process pending AddInputRec callbacks. The queue is emptied, and
* each pending callback is made. Memory for each AddInputRec is freed.
* This routine executes at non-AST level.
*/
static void AddInputCallback()
{
unsigned long status;
AddInputRec *addInputRecP;
sys$clref (addInputEfn);
while (lib$remqhi (addInputQueueHeaderA, &addInputRecP, 0) !=
LIB$_QUEWASEMP) {
(*addInputRecP->routineP) (addInputRecP->closure);
XtFree (addInputRecP->mallocP);
}
}
/* CompletionAst is the routine to be used in all asynchronous system
* service calls as the AST completion routine. It is passed the
* address of an AddInputRec containing the application's completion
* callback routine address and parameter. The AddInputRec is queued
* onto the list of pending callbacks, and the XtAddInput event flag
* is set, notifying the Xt toolkit that there is something to do.
* This routine executes at AST level.
*/
static void CompletionAst(addInputRecP)
AddInputRec *addInputRecP;
{
lib$insqti (addInputRecP, addInputQueueHeaderA, 0);
sys$setef (addInputEfn);
}
/* AllocateAddInputRec is called by the application just before starting
* an asynchronous system service. It is passed the application's
* completion routine address and parameter. An AddInputRec is XtMalloc'ed,
* the routine address and parameter are saved in this block, and the
* address of the block is returned. This AddInputRec address should
* then be passed as the AST completion routine parameter (ASTPRM) to
* the system service call. Eventually, this AddInputRec will be passed
* to the "CompletionAst" routine, where it will be added to the addInputQueue
* (at AST level). When AddInputCallback is finally called, the
* AddInputRec will be removed from the addInputQueue, the callback it
* describes will be called, and the block will be XtFree'd.
*/
static AddInputRec *AllocateAddInputRec(routineP, closure)
void (*routineP)();
Opaque closure;
{
char *mallocP;
AddInputRec *addInputRecP;
mallocP = XtMalloc (sizeof (AddInputRec) + 7);
addInputRecP = (AddInputRec *)(((int)(mallocP) + 7) & (-8));
addInputRecP->mallocP = mallocP;
addInputRecP->routineP = routineP;
addInputRecP->closure = closure;
return (addInputRecP);
}
----------------------------------------------------------------------
Then, add the following XtAddInput call right before your call to XtMainLoop
(or whatever):
XtAddInput (addInputEfn, 0, AddInputCallback, 0);
----------------------------------------------------------------------
Finally, whenever you code an asynchronous system service, use the following
example. The IOSB must be in your context block so that you can find and
check it after the operation really completes. Always supply "CompletionAst"
as the AST completion routine - this routine will trigger the XtAddInput
thread. Call "AllocateAddInputRec", passing it your actual completion routine
and the parameter you want passed to it. This will allocate (XtMalloc)
a control block and will pass it to "CompletionAst" when the I/O actually
completes. Eventually, your own callback routine ("ReadCompleteCallback" in
this example) will be called, with your own callback parameter ("contextP" in
this example) as its first and only parameter, at non-AST level, between
other event processing. The work done at AST level is never seen by
the rest of the application.
** status = sys$qio (
miscEfn, /* use misc event flag */
** contextP->chan, /* (your) device channel */
** IO$_READVBLK|IO$M_TIMED|IO$M_NOECHO, /* (your) operation and flags */
** contextP->iosbA, /* (your) IOSB */
CompletionAst, /* special completion AST */
AllocateAddInputRec ( /* special AST parameter */
** ReadCompleteCallback, /* (your) completion routine */
** contextP), /* (your) completion param */
** contextP->bufferP, /* (your) buffer */
** contextP->bufLen; /* (your) buffer length */
** 0, 0, 0, 0); /* (your) other QIO parms*/
In this call, the lines with "**" at the beginning are things that you
need to supply. The other lines should be coded exactly as shown.
Hope this helps.
-steve-
|