eygle.com   eygle.com
eygle.com eygle
eygle.com  
 
Digest Net: August 2008 Archives

August 2008 Archives

Compare-and-swap

| 7 Comments

from Wikipedia
In computer science, the compare-and-swap CPU instruction ("CAS") (or the Compare & Exchange - CMPXCHG instruction in the x86 and Itanium architectures) is a special instruction that atomically compares the contents of a memory location to a given value and, if they are the same, modifies the contents of that memory location to a given new value. The result of the operation must indicate whether it performed the substitution; this can be done either with a simple boolean response (this variant is often called compare-and-set), or by returning the value read from the memory location (not the value written to it).

CAS is used to implement synchronization primitives like semaphores and mutexes, as well as more sophisticated lock-free and wait-free algorithms. Maurice Herlihy (1991) proved that CAS can implement more of these algorithms than atomic read, write, and fetch-and-add, and that, assuming a fairly large amount of memory, it can implement all of them [1].

Algorithms built around CAS typically read some key memory location and remember the old value. Based on that old value, they compute some new value. Then they try to swap in the new value using CAS, where the comparison checks for the location still being equal to the old value. If CAS indicates that the attempt has failed, it has to be repeated from the beginning: the location is re-read, a new value is computed and the CAS is tried again.

Some of these algorithms are affected by and must handle the problem of a false positive match, or the ABA problem. It's possible that between the time the old value is read and the time CAS is attempted, some other processors or threads change the memory location two or more times such that it acquires a bit pattern which matches the old value. The problem arises if this new bit pattern, which looks exactly like the old value, has a different meaning: for instance, it could be a recycled address, or a wrapped version counter.

CAS, and other atomic instructions, are unnecessary in uniprocessor systems, because the atomicity of any sequence of instructions can be achieved by disabling interrupts while executing it. However, often disabling interrupts is too expensive to be practical, so even programs only intended to run on uniprocessor machines will benefit by using them, as in the case of Linux's futexes.

In multiprocessor systems, it is impossible and undesirable to disable interrupts on all processors at the same time. Even with interrupts disabled, two or more processors could be attempting to access the same semaphore's memory at the same time. The compare-and-swap instruction allows any processor to atomically test and modify a memory location, preventing such multiple processor collisions.

Basics of C within the Oracle kernel

| 13 Comments
出处:
http://www.oraclefans.cn/forum/showtopic.jsp?rootid=3530&CPages=1
         

C is a function based language and as with most languages is composed of
declarations and statement blocks.

Below is a very simple example and even this example uses 5 functions:

        strcat(),strcpy(),write(),strlen() and print_string().

                ***************

char text_string[100];

print_string()
{
char output_string[100];

strcpy(output_string,"C is a wonderful language"); /* Copy string */

strcat(output_string,text_string);                /* Concatentate string */

if (write(1,output_string,strlen(output_string))<0)/* Write output */
    return false;
else
    return true;
}

main()
{
  strcpy(text_string," but C++ is better still");

  if (!print_string())
    /* error handling */
    ;
}

An equivalent in pl/sql would be :

declare

text_string    varchar(100);

function print_string return boolean
as
    output_string varchar(100);
  begin
    output_string := 'C is a wonderful language';

    output_string := output_string || text_string;

    dbms_output.put_line(output_string);

    return true;
  end;

begin

  text_string := ' but C++ is better still';

  if (not print_string)
  then
        /* Error handling */
        null;
  end if;

end;

                ***************

Rather than just document the basic C commands , I have taken one
particular kernel module (ksl) and highlighted the most
significant C commands and Oracle coding techniques.

I have avoided adding my own comments to the source files as these would
get lost among the numerous coding comments. Instead I have added markers
against which detailed notes are provided below.

        Header file marker : !!*** H xx ***!!!
        Source file marker : !!*** C xx ***!!!

        Notes to the extract from ksl.h
        ===============================

ksl.h          - Kernel Service Locking.
=====

In general header files are used for the main declarations.

Comments                                !!!*** H 01 ***!!!
--------

As in pl/sql, comments begin with /* and end with */ .

Compile time directives                !!!*** H 02 ***!!!
-----------------------

Commands which are pre-processed by the compiler start with #.

Conditional compilation                !!!*** H 02 ***!!!
-----------------------

To conditionally compile code you use the #ifdef / #ifndef directive.

In kernel header files there will be a list of other header files to be
included. The #ifndef is used to prevent a header file being included twice.

Including other source/header files    !!!*** H 02 ***!!!
-----------------------------------

To include header and/or source files you use the compile time
directive #include. Include files can be nested to many levels.

PUBLIC TYPES AND CONSTANTS              !!!*** H 03 ***!!!
--------------------------

All declarations between
        /* PUBLIC TYPES AND CONSTANTS */
    and
        /* PRIVATE TYPES AND CONSTANTS */

are available to other layers within the kernel.

The 'define' preprocessor command      !!!*** H 04 ***!!!
---------------------------------

The define command is used to create macros which are then expanded by the
preprocessor.

This command is used extensively throughout the kernel and its use ranges
from defining maximum values through to complete code segments.

In general if an identifier is in uppercase then it represents a macro.

Function declarations                  !!!*** H 05 ***!!!
---------------------

For ANSI compliance , public functions are declared within the header files.

word    kslget(/*_ struct ksllt *id, word wait _*/);

  where  word  - the datatype of the return value from the function.

          kslget- function name, max 6 characters.

          (/*_ xxx,yyy, _*/)

                - xxx,yyy - arguments for function.

                /*_ _*/  - used by olint to check that this function is
                            being called with the correct number of arguments.

Using defines to represent functions    !!!*** H 06 ***!!!
------------------------------------

It is often the case that functions are replaced by macros , mainly
for performance - inline code is faster than function calls.

Using defines to represent code segments !!!*** H 07 ***!!!
----------------------------------------

Datatypes                                !!!*** H 08 ***!!!
---------

C variables can be simple or complex (records) and either a scalar or an array.

The typedef command is crucial to the understanding of variable declarations.
Throughout the kernel, no reference is ever made to the basic C types such
as int or char. Instead all the C types are 'aliased' via the typedef command.

  e.g.    typedef unsigned int ub4

          ub4 my_integer;

        is equivalent to

          unsigned int my_integer;

The importance of typedef for the C datatypes cannot be overstated - any
developer who used the C datatypes directly would have a very short career.
The cornerstone of portability is the correct use of datatypes.

See oratypes.h for a complete list of the 'aliases' for the C datatypes.

Records                                !!!*** H 08 ***!!!
-------

In C, records are called structures and are declared with the 'struct'
command.

Refering to struct ksllt:

        ub4          kslltwgt;            Simple variable.
  ...
        struct ksllt *kslltchn;            Pointer to record.
  ...
        ub4          ksllthst[KSLHSTMAX]; Simple variable array.

Pointers and pointers to functions      !!!*** H 09 ***!!!
----------------------------------

For those unfamiliar to C , one of the hardest concepts to grasp is
the notion of pointers.

Instead of declaring a variable and its storage area, you can declare
a variable which points to the memory area where the data is actually
stored. This data could be an integer number, a text string and most
importantly of all a function.

A variable is declared a pointer by prefixing '*' to the identifier name.

The use of pointers and pointers to functions is fundamental not only to
the Oracle kernel but to most software written in C.

Refering to struct  kslld :

        text  *kslldnam;      Pointer to a text string which contains
                                the latch name ( v$latchname ).
    ...
        void  (*kslldcln)(/*_ word action, ksllt *lp _*/);
                                Pointer to a function for latch cleanup.


Notifiers                              !!!*** H 10 ***!!!
---------

Each layer within the kernel has a notifier function used during
instance startup.

Registration defines                    !!!*** H 11 - H 15 ***!!!
--------------------

There are numerous registration defines which are processed by other
kernel modules in order to build a single data structure to represent
information registered by different kernel layers - e.g. init.ora parameters.

  SGA variables                        !!!*** H 11 ***!!!

  PGA variables                        !!!*** H 12 ***!!!

  Events                                !!!*** H 13 ***!!!

  X$ tables                            !!!*** H 14 ***!!!

  init.ora parameters                  !!!*** H 15 ***!!!

Apart from X$ tables, the #define which preceeds the KSP registration is the
one used within the source and not the _ identifier.


        Notes to the extract from ksl.c
        ===============================

ksl.c          - Kernel Service Locking.
=====

Function Definition                            !!!*** C 01 ***!!!
-------------------

A function starts with its name and argument list, followed by a
declaration of the argument types.

Local Variable declarations                    !!!*** C 02 ***!!!
---------------------------

Variables only available within this function.

Variables are in fact declared at the start of a statement block, so
it is possible to have nested declarations.

i.e.  func(a)
      int a;
      {
        int b;
        b=1;
        { int b;
          b=1;
          { int b;
            b=1;
          }
        }
      }

The normal rules of scope apply - inner declarations have precedence
over outer.

Assignments                                    !!!*** C 03 ***!!!
-----------

In C, the assignment operator is =, which is one of the main
causes of coding error as you would normally expect this operator
to represent equality.

Raising internal (600) errors                  !!!*** C 04 ***!!!
-----------------------------

Within the kernel, ora-600 errors are identified by the wrapper
OERI() and are raised by either the ksesic() or ASSERT() functions.

Raising Oracle Errors.
---------------------

Oracle error numbers are identified by the wrapper OER() and are
raised by the ksesec() functions.

The use of the OER() wrapper is not guaranteed within pl/sql.

Checking for Events
-------------------

The ksepec() function is passed one argument, an OER() number, and
returns the current level number. If level number is zero then this
event has not been set.

Bit manipulation                                !!!*** C 05 ***!!!
----------------

Bit functions are used to test,set and clear bits.

        bit()  - test
        bis()  - set
        bic()  - clear.

These functions are in fact macros.

Conditional Evaluation                          !!!*** C 06 ***!!!
----------------------

The control statements such as 'if', 'for' and 'while' have no
equivalent end statement such as 'endif'. They control the execution
of the next statement block.

Pointer referencing                            !!!*** C 07 ***!!!
-------------------

Pointer referencing of structure ( record ) variables is done
with the '->' operator.

Address parameters                              !!!*** C 08 ***!!!
------------------

The '&' operator before a variable passes the address of the
variable to sclgtf() .

Operating System Dependent (OSD) routines      !!!*** C 08 ***!!!
-----------------------------------------

In general osd routines begin with the letter s.

Calling a function via a pointer                !!!*** C 09 ***!!!
--------------------------------

The function call (*kglger)() is an example of calling a
function indirectly. The function actually being called is kslges().

'for' control loop                              !!!*** C 10 ***!!!
------------------

One of the most common control structures used in C.

The 'for' control statement contains an initial expresion,
an evaluation expression and a next iteration expression.

If the evaluation is true then the enclosing statement block
is executed.

i.e. for (i=0;i<10;i++)
      { printf("The value of i is %d\n",i); }


To terminate the loop, you can use the break statement .

To branch back to the control expression, you can use the continue
statement.

Equality operator                              !!!*** C 11 ***!!!
-----------------

The equality operator is '==' and NOT '='.

And / Or operators                              !!!*** C 12 ***!!!
------------------

The 'and' operator is '&&', the 'or' operator '||'.

e.g. pl/sql :  if ( test_value = 10 or ( a = 5 and b = 6 ) )

    becomes in C :

              if ( test_value == 10 || ( a ==5 && b == 6 ))

Output to trace and alert files                !!!*** C 13 ***!!!
-------------------------------

ksdwrf() function : write to trace file.

ksdwra() function : write to alert file.


                Extract from ksl.h
                ==================

        !!!*** H 01 ***!!!
/*
* $Header: ksl.h,v 1.44.710.5 94/07/07 11:58:37 ksriniva: Exp $ ksl.h
*/


        !!!*** H 02 ***!!!

#ifndef  SE
#include <se.h>
#endif
#ifndef  SC
#include <sc.h>
#endif
#ifndef  SM
#include <sm.h>
#endif
#ifndef  SP
#include <sp.h>
#endif
#ifndef  SLO
#include <slo.h>
#endif
#ifndef  KSM
#include <ksm.h>
#endif
#ifndef  KGSL
#include <kgsl.h>
#endif
#ifndef  KQF
#include <kqf.h>
#endif
#ifndef KSP
#include <ksp.h>
#endif
#ifndef  KSD
#include <ksd.h>
#endif
#ifndef  KSE
#include <kse.h>
#endif
#ifndef KVI
#include <kvi.h>
#endif

#ifndef  KSL
#define  KSL

/***********/
/* LATCHES */
/***********/

/* Set KSLDEBUG to debug systems that hang waiting for latches that no one
* is holding.  This can happen if someone does a fast latch get and then
* exits the block and gets another latch.
*/
/* #define KSLDEBUG 1 */

#ifdef KSLDEBUG
#  define KSLDBG(exp) exp
#else
#  define KSLDBG(exp)
#endif



/* A latch is a type  of  lock that can be  very quickly acquired and freed.
* Latches are  typically used to    prevent  more  than one process  from
* executing the same  piece of  code at  a given time.  Contrast  this with
* enqueues  which  are usually  used to prevent  more than one process from
* accessing the same data structure at a given  time.  Associated with each
* latch is a cleanup procedure that will be called if a process  dies while
* holding  the latch.  Latches  have an  associated level  that  is used to
* prevent deadlocks.  Once a process acquires a latch at a certain level it
* cannot subsequently acquire a latch at a  level that is equal to  or less
* than that level (unless it acquires it nowait).
*/


        !!!*** H 03 ***!!!

/* PUBLIC TYPES AND CONSTANTS */

        !!!*** H 04 ***!!!

#define KSLMXLATCH 60 K_MLSIF(+6)
  /** maximum number of latches.  To increase, just                        **
  ** change, recompile ksmp.c and ksl.c.  This could be eliminated, but it **
  ** doesn't seem worth the extra code.                                    */

/* the pointer to the latch object (ksllt) is public */

/* PUBLIC PROCEDURES */

        !!!*** H 05 ***!!!

word    kslget(/*_ struct ksllt *id, word wait _*/);
  /*
  ** Get the latch specified by "id",  on  behalf  of  the  current
  ** session.  If "wait" is FALSE, return immediately if the  latch
  ** is in use; if TRUE, keep trying and return when the latch  has
  ** been granted.  Return TRUE  if  and  only  if  the  latch  was
  ** granted.
  **
  ** In order to  prevent deadlocks,  this procedure checks  for
  ** errors in latch  sequence based on  level.  Once  a  process
  ** acquires a latch at a certain level it  cannot acquire another
  ** latch at  a level less  than or equal to  that level.  There are
  ** two exceptions to this rule.  One, a process may acquire a latch
  ** at any level if it has not acquired a latch at that level and
  ** it acquires the latch nowait.  Two, a process may acquire
  ** exactly one duplicate latch (latch at the same level as another
  ** latch) if it acquires it nowait.
  **
  ** This routine will  raise an error if  called  during  cleanup,
  ** with "wait" equal to TRUE, and the latch is busy.  This is so
  ** PMON does not get stuck acquiring a latch.
  */

        !!!*** H 06 ***!!!

/* word kslgetd(struct ksllt *lt, word wait, CONST char *comment); */
#define kslgetd(lt, wait, comment) ((kslcmt = (comment)), kslget((lt), (wait)))
  /*
  ** NEW: kslgetd() is the new debugging version of kslget().  It takes
  ** an additional comment string as an argument.  If the latch trace
  ** event (currently event # 10005) is turned on, this comment is
  ** associated with the latch.  If a latch hierarchy error occurs later
  ** on while this latch is still held, the latch dump routines will also
  ** print the relevant comment strings.
  ** Warning: the comment string must persist for the lifetime of the PGA;
  ** ideally, it should be a literal constant.
  */


void    kslfre(/*_ struct ksllt *id _*/);
  /*
  ** Free the latch specified by "id", on  behalf  of  the  current
  ** session.
  */

/* void kslfred(struct ksllt *lt, CONST char *comment); */
#define kslfred(lt, comment) ((kslcmt = (comment)), kslfre((lt)))
  /*
  ** NEW: kslfred() is the new debugging version of kslfre().  It takes
  ** an additional comment string as an argument.  If the latch trace
  ** event (currently event # 10005) is turned on, this comment is
  ** associated with the latch.  If a later attempt is made to free this
  ** latch before it is gotten again, the latch dump routines will also
  ** print the relevant comment strings.
  ** Warning: the comment string must persist for the lifetime of the PGA;
  ** ideally, it should be a literal constant.
  */


/* Fast latching macros.  These macros can be used to very quickly get and
* free a latch. The KSLBEGIN macro gets the latch (in wait mode) and the
* KSLEND macro frees the latch.  The code in between the two macros executes
* with the latch held.
*
* The code between the KSLBEGIN and KSLFREE may not non-locally exit (return,
* break, continue). However, it may signal an error.  Between the KSLBEGIN and
* the KSLEND you may not get or free another latch. (however, see KSLUPGRD).
*
* WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
* If you need to use an ONERROR block in the protected code, don't use the
* fast latching macros!  Just use the regular kslget/kslfre mechanism.
*
* Example usage:
*
*  void foo()
*  {
*    KSLBEGIN(foolatch)                /0 get the latch 0/
*      protected_code;
*      more_protected_code;
*    KSLEND                            /0 free the latch 0/
*  }
*/

        !!!*** H 07 ***!!!

#define KSLBEGIN(atmlatch)\
if (1)\
{\
  reg ksllt *atmlat = (atmlatch);\
  reg kslla *atmsta = ksuglk(ksugcp());\
  serc atmse;\
  if (bit(atmsta->ksllalow, ksllvl.ksllvbits[atmlat->kslltlvl]) \
      KSLDBG(|| atmsta->ksllalaq))\
    DISCARD kslget(atmlat, 1);\
  atmsta->ksllalaq = atmlat;\
  if (sclgtf(&atmlat->kslltlat))\
  { \
    atmlat->kslltwgt++;\
    kslprrc(atmlat, TRUE);\
  } \
  else DISCARD kslges(atmlat, 1);

#define KSLEND \
  if (!sclfr(&atmse, &atmlat->kslltlat)) kslferr(&atmse);\
  kslprrc(atmlat, FALSE); \
  atmsta->ksllalaq = (ksllt *)0;\
} else DISCARD(0);



/* KSLUPGRD upgrades the state of a latch gotten using KSLBEGIN to be
* the same as the state of a latch gotten using kslget.  This allows the
* latch to be freed using kslfre and it allows another latch to be gotten.
* If a latch is upgraded it cannot be freed using KSLEND unless the latch is
* first downgraded using KSLDNGRD.  KSLUPGRD and KSLDNGRD can only be
* invoked in the code that is textually between the KSLBEGIN and KSLEND.
* N.B. KSLUPGRD cannot be used on latches gotten using KSLNBEGIN.
*/

#define KSLUPGRD \
if (1)\
{\
  if (0 KSLDBG(|| atmsta->ksllalaq != atmlat))\
    ksesic0(OERI(501));\
  bis(atmsta->ksllalow, 1 << atmlat->kslltlvl);\
  atmsta->ksllalat[atmlat->kslltlvl] = atmlat;\
  atmlat->kslltefd = kgetfd(ksmgpga);\
  KSLDBG(atmsta->ksllalaq = (ksllt *)0;)\
} else DISCARD(0)\

#define KSLDNGRD \
if (1)\
{\
  if (0 KSLDBG(|| atmsta->ksllalat[atmlat->kslltlvl] != atmlat))\
    ksesic0(OERI(502));\
  atmsta->ksllalaq = atmlat;\
  bic(atmsta->ksllalow, 1 << atmlat->kslltlvl);\
  atmsta->ksllalat[atmlat->kslltlvl] = (ksllt *)0;\
} else DISCARD(0)\


        _______________  CODE removed __________________

/* PRIVATE TYPES AND CONSTANTS */


/* Maximum  latch level.  Note that  the  level immediately above this is
* reserved for getting a duplicate latch (in nowait mode).
*/
#define  KSLLMXLV 8                  /* maximum value for kslldlev in kslld */
                /* NOTE: ksllalow and ksl.c need to change if KSLLMXLV >= 14 */
                      /* also the levelbits in kslget need to change as well */

struct ksllvlt                            /* level bits, used by get macros */
{
  BITS16 ksllvbits[KSLLMXLV+2];
};
typedef struct ksllvlt ksllvlt;


/* get latch slow, called by latch get macros */
word kslges(/*_ struct ksllt *l, eword from_macro _*/);

/* latch free error, called by latch get macros */
void kslferr(/*_ serc *se _*/);


/* Latch instance.  The  latch instance is  the actual  unit of locking  (it
* contains the OSD latch structure).
*
* There can be more than one latch with the same name (if they are allocated
* dynamically).  In this case there is one master latch allocated statically
* called the parent latch and a number of dynamically allocated latches
* called the child latches.  The latches are chained together to
* facilitate statistics gathering.
*/

        !!!*** H 08 ***!!!

struct ksllt
{
  sclt          kslltlat;                            /* OSD latch structure */

  eword        kslltefd; /* error frame depth when gotten, this is used to */
          /* free the latch if an error is signalled while the latch is held */

  ub4          kslltngt;                  /* count  of times gotten nowait */
  ub4          kslltnfa;              /* count of times failed nowait get */

  ub4          kslltwgt;                    /* count of times gotten wait */
  ub4          kslltwff;      /* count of wait gets that failed first try */
  ub4          kslltwsl;  /* count of times slept when failed to get latch */

  struct ksllt *kslltchn;          /* ptr to next child latch of this chain */
  eword        kslltlvl;              /* latch level, to enforce hierarchy */
  b1            kslltnum;            /* latch number, to index descriptors */

  struct kslla *kslltwkp;  /* process that is sleeping and should be woken */
  /* this is a hint, the system will work though slower if this is not done */

  ub4          kslltwkc;          /* count of wakeups that have been done */

  ub4          kslltwth;/* count of sleeps that were holding another latch */

#define KSLHSTMAX 12            /* if you change this, must change x$ table */
  ub4          ksllthst[KSLHSTMAX];
  /* Histogram of max exponential backoff per miss. The actual sleep time
    * corresponding to each bucket in the histogram is about
    * 2**((bucket+1)/2)-1 plus the sleep time of all the lower buckets.
    * All max exponential backoffs greater than the highest bucket are
    * added to the highest bucket.
    */
  dvoid        *kslltrec;                  /* recovery info for this latch */
};
typedef struct ksllt ksllt;


        !!!*** H 09 ***!!!

/* Latch descriptor.  An array of these is allocated in the  PGA.  The array
* contains  a latch  descriptor for  every  latch.  The  latch  descriptor
* contains    static information about that    latch (such  as  the cleanup
* procedure for the latch) that cannot be pointed at from the SGA  (because
* it is allocated in each process).  It is found using the latch number.
*/
struct  kslld
{
  text  *kslldnam;                            /* human-readable latch name */
  void  (*kslldcln)(/*_ word action, ksllt *lp _*/);        /* cleanup proc */
  void  (*kslldgcl)(/*_ kgsmp *gp, word action, struct kgslt *lp _*/);
                        /* cleanup procedure for a generic component's latch */
  size_t  kslldrsz;                              /* recovery structure size */
  b1      kslldlvl;                                          /* latch level */
  b1      kslldpnt;                /* TRUE if parent of a class of latches */
  ub1    kslldlng;          /* TRUE if latch can be held for long periods */
};
typedef  struct  kslld kslld;

#define KSLLDMNAM 50                          /* max size of the name field */

typedef  ksllt  *kslltb[KSLMXLATCH];      /* for pga latch table declaration */
externref        CONST_W_PTR kslld kslldt[];  /* table of latch descriptors */
void    kslenl(/*_ void (*enumpr)(ksllt *l, ptr_t ctx), ptr_t ctx _*/);
                                                            /* enumerate all */

typedef bitvec ksllbv[BITVEC(KSLMXLATCH)];            /* latch number bitvec */

/* initialize recovery structures for latches */
void kslirs(/*_ void _*/);

void    ksldlt(/*_ word level _*/ );                        /* latch trace */

/* latch debugging: various bit values for the PGA variable ksldbg */
#define KSLDBGTRC 0x1                          /* trace latching operations */
#define KSLDBGPRT 0x2                    /* protect/unprotect recovery areas */

/*******************/
/* WAIT/POST/EVENT */
/*******************/

/* PUBLIC PROCEDURES */

word    kslaer(/*_ word nevent _*/);
  /*
  ** KSLAER: Allocate event range.  Allocate (permanently)
  ** nevent events, return base.
  ** Callable during or after KSCNISGA,  NOT latched.
  */


        _______________  CODE removed __________________

/*********************/
/* misc. definitions */
/*********************/

        !!!*** H 10 ***!!!

void kslnfy(/*_ word nfytype, ptr_t ctx _*/);                    /* notifier */

/* fixed table callback routine */
dvoid *ksltbl(/*_ CONST struct kqfco *cd, COLID ncols, ptr_t ctx, kghds *heap,
                  bitvec *whichcols, word msg, word (*rf)(ptr_t row) _*/);

/* fixed table callback for latch name */
size_t kslgnm(/*_ uword index, ptr_t space _*/);

#endif                                                                /* KSL */

/* register notifier proc */
KSCNTBDV(FADDR(kslnfy), (1<<KSCNISGA)|(1<<KSCNASGA))

/* number of latches as SGA variable */
#define kslltl KVIISDN(kslltl_)
KVIISDV(kslltl_, "kslltl", "number of latches")

/* latch table for display program */
#define kslltt KSMSGADN(kslltb, kslltt_)
KSMSGADV(kslltb, kslltt_)

#define kslerb KVIISDN(kslerb_)                          /* event range base */
KVIISDV(kslerb_, "kslerb", "event range base")

#define kslnbe KVIISDN(kslnbe_)                          /* # of base events */
KVIISDV(kslnbe_, "kslnbe", "# of base events")

        !!!*** H 11 ***!!!

/* event statistics array: 1 for the system + 1 per session */
#define kslesa KSMSGADN(ksles *, kslesa_)
KSMSGADV(ksles *, kslesa_)

/* level bits for macros to use */
#define ksllvl KSMSGADN(ksllvlt, ksllvl_)
KSMSGADV(ksllvlt, ksllvl_)

/* number of CPUs in the system */
#define kslcpu KVIISDN(kslcpu_)
KVIISDV(kslcpu_, "kslcpu", "number of CPUs in the system")


#ifndef SYS_SNGL
#define kslrov KSMPGADN(kslrov_)                    /* pga rover for kslpse */
KSMPGADV(struct ksupr *, kslrov_)
#endif                                                          /* SYS_SNGL */

        !!!*** H 12 ***!!!

#define kslbwt KSMPGADN(kslbwt_)    /* beginning time of current wait event */
KSMPGADV(ub4, kslbwt_)

#define ksllsp KSMPGADN(ksllsp_)            /* last wait resulted in post ? */
KSMPGADV(word, ksllsp_)

#define ksltri KSMPGADN(ksltri_)                  /* trace info for latches */
KSMPGADV(struct ksltr *, ksltri_)

#define ksldbg KSMPGADN(ksldbg_)                /* latch debugging enabled ? */
KSMPGADV(ub1, ksldbg_)

#define kslcmt KSMPGADN(kslcmt_)                          /* tracing comment */
KSMPGADV(CONST char *, kslcmt_)

        !!!*** H 13 ***!!!

/* latch activity event */
#define ksllae KSLEVTDN(ksllae_)
KSLEVTDV3(ksllae_, "latch activity", "address", "number", "process#")

/* latch free event */
#define ksllfe KSLEVTDN(ksllfe_)
KSLEVTDV3(ksllfe_, "latch free", "address", "number", "tries")

/* TRACES */
KSDTRADV("LATCHES", FADDR(ksldlt))                            /* latch dump */

KSDEVCBF(OER(10005), FADDR(kslcbf))                      /* latch op tracing */

KSDEVCBF(OER(10072), FADDR(kslrpc))      /* latch recovery memory protection */

/* session initialization */
KSMUGIFR(FADDR(kslies))

        !!!*** H 14 ***!!!

/* fixed tables */
/* latch objects */
KQFTABC(ksllt, ksllt_c,  "X$KSLLT", ksltbl, sizeof(ksllt ***), KQFOB081, 5)
KQFCINT(ksllt, kslltnum,  "KSLLTNUM")
KQFCINT(ksllt, kslltlvl,  "KSLLTLVL")
KQFCFST(ksllt, "KSLLTNAM", KSLLDMNAM, kslgnm, kslgnm_n)
KQFCINT(ksllt, kslltngt,  "KSLLTNGT")
KQFCINT(ksllt, kslltnfa,  "KSLLTNFA")
KQFCINT(ksllt, kslltwgt,  "KSLLTWGT")
KQFCINT(ksllt, kslltwff,  "KSLLTWFF")
KQFCINT(ksllt, kslltwkc,  "KSLLTWKC")
KQFCINT(ksllt, kslltwsl,  "KSLLTWSL")
KQFCINT(ksllt, kslltwth,  "KSLLTWTH")
KQFCINT(ksllt, ksllthst[0], "KSLLTHST0")
KQFCINT(ksllt, ksllthst[1], "KSLLTHST1")
KQFCINT(ksllt, ksllthst[2], "KSLLTHST2")
KQFCINT(ksllt, ksllthst[3], "KSLLTHST3")
KQFCINT(ksllt, ksllthst[4], "KSLLTHST4")
KQFCINT(ksllt, ksllthst[5], "KSLLTHST5")
KQFCINT(ksllt, ksllthst[6], "KSLLTHST6")
KQFCINT(ksllt, ksllthst[7], "KSLLTHST7")
KQFCINT(ksllt, ksllthst[8], "KSLLTHST8")
KQFCINT(ksllt, ksllthst[9], "KSLLTHST9")
KQFCINT(ksllt, ksllthst[10], "KSLLTHST10")
KQFCINT(ksllt, ksllthst[11], "KSLLTHST11")
KQFENDT(ksllt)

/* latch descriptor */
KQFTABL(kslld, kslld_c, "X$KSLLD", kslldt, kslltl, KQFOB082, 1)
KQFCSTP(kslld, kslldnam, "KSLLDNAM")
KQFENDT(kslld)

/* event descriptors */
KQFTABL(ksled, ksled_c, "X$KSLED", ksledt, kslnbe + 1, KQFOB182, 1)
KQFCSTP(ksled, kslednam, "KSLEDNAM")
KQFCSTP(ksled, ksledp1, "KSLEDP1")
KQFCSTP(ksled, ksledp2, "KSLEDP2")
KQFCSTP(ksled, ksledp3, "KSLEDP3")
KQFENDT(ksled)

/* event statistics for all sessions */
KQFTABL(ksles, ksles_c, "X$KSLES", &kslesa[kslnbe + 1],
        ((kslnbe + 1) * ksusga.ksusgsel), KQFOB183, 2)
KQFCFIN(ksles, "KSLESSID", FADDR(kslgse), kslgse_n)
KQFCFIN(ksles, "KSLESENM", FADDR(kslgne), kslgne_n)
KQFCUIN(ksles, ksleswts, "KSLESWTS")
KQFCUIN(ksles, kslestmo, "KSLESTMO")
KQFCUIN(ksles, kslestim, "KSLESTIM")
KQFENDT(ksles)

/* instance-wide event statistics */
KQFTABL(ksles, kslei_c, "X$KSLEI", kslesa, (kslnbe + 1), KQFOB190, 2)
KQFCFIN(ksles, "KSLESWTS", FADDR(kslgwe), kslgwe_n)
KQFCFIN(ksles, "KSLESTMO", FADDR(kslgto), kslgto_n)
KQFCFIN(ksles, "KSLESTIM", FADDR(kslgte), kslgte_n)
KQFENDT(ksles)


        !!!*** H 15 ****!!!

/* spin count when fail to get latch */
#define kslspc KSPPARDN(kslspc_)
KSPPARDV("_latch_spin_count", kslspc_, kslspc_s, kslspc_l, kslspc_p,
        LCCMDINT, 0, NULLP(text), 100, KSPLS1(NULLP(text)),
        KSPLS2(1, EWORDMAXVAL), 0, KSPLS1(NULLP(word)),
        "amount to spin waiting for a latch")

/* holds value of kslspc */
#define kslspi KSMSGADN(eword, kslspi_)
KSMSGADV(eword, kslspi_)


/* max amount to sleep when waiting for a latch and holding another */
#define kslmxs KSPPARDN(kslmxs_)
KSPPARDV("_max_sleep_holding_latch", kslmxs_, kslmxs_s, kslmxs_l, kslmxs_p,
        LCCMDINT, 0, NULLP(text), 4, KSPLS1(NULLP(text)),
        KSPLS2(0, EWORDMAXVAL), 0, KSPLS1(NULLP(word)),
        "max time to sleep while holding a latch")

/* holds value of kslmxs */
#define kslmsl KSMSGADN(eword, kslmsl_)
KSMSGADV(eword, kslmsl_)


/* maximum sleep during any exponential backoff in hundreths of seconds */
#define kslmes KSPPARDN(kslmes_)
KSPPARDV("_max_exponential_sleep", kslmes_, kslmes_s, kslmes_l, kslmes_p,
        LCCMDINT, 0, NULLP(text), 0, KSPLS1(NULLP(text)),
        KSPLS2(0, EWORDMAXVAL), 0, KSPLS1(NULLP(word)),
        "max sleep during exponential backoff")

/* holds value of kslmes */
#define kslmex KSMSGADN(eword, kslmex_)
KSMSGADV(eword, kslmex_)


/* if this is 1 then we use the post waiters protocol for latches that
* are declared KSLLALNG, if it is greater than one we use it for all
* latches.
*/
#define kslpsw KSPPARDN(kslpsw_)
KSPPARDV("_latch_wait_posting", kslpsw_, kslpsw_s, kslpsw_l, kslpsw_p,
        LCCMDINT, 0, NULLP(text), 1, KSPLS1(NULLP(text)),
        KSPLS2(0, EWORDMAXVAL), 0, KSPLS1(NULLP(word)),
        "post sleeping processes when free latch")

/* holds value of kslpsw */
#define kslpwt KSMSGADN(eword, kslpwt_)
KSMSGADV(eword, kslpwt_)

/* latch recovery alignment parameter:
* specifies a list of latch numbers for which recovery alignment is enabled.
* valid numbers are [0...max_latches); if any number in the list is outside
* the range, then it is ignored (note that the default value is KSLMXLATCH
* - not 0 -, which causes no alignment to be enabled).  If any number in the
* list is "999", then recovery alignment is enabled for ALL latches which are
* defined through one of the new compile-time service macros KSLLTDV2 or
* KGSLLDV2.  Use the "LATCH#" column in V$LATCH to get latch numbers.
*/
#define kslrpp KSPPARDN(kslrpp_)
KSPPARDV("_latch_recovery_alignment", kslrpp_, kslrpp_s, kslrpp_l, kslrpp_p,
        LCCMDINT, 0, NULLP(text), KSLMXLATCH, KSPLS1(NULLP(text)),
        KSPLS2(0, EWORDMAXVAL), 0, KSPLS1(NULLP(word)),
        "align latch recovery structures")

/* holds value of kslrpp converted to a bitvec */
#define kslrpv KSMSGADN(ksllbv, kslrpv_)
KSMSGADV(ksllbv, kslrpv_)

/* latch that synchronizes latch wait list */
#define kslwlst KSLLATDN(kslwlst_)           
KSLLATDV(kslwlst_, "latch wait list", FADDR(ksllcu), KSLLMXLV+1)


                Extract from ksl.c
                ==================

/*
** Get the latch specified by "id", on behalf  of  the  current
** session.  If "wait" is  FALSE,  return  immediately  if  the
** latch is in use; if TRUE, keep trying and  return  when  the
** latch has been granted.  Return TRUE  if  and  only  if  the
** latch was granted.  Raise an error if this is cleanup,  wait
** is TRUE, and the latch is busy.  This procedure  checks  for
** errors in latch sequence (based on level), and records  what
** latches are held so they can be freed if needed.
*/
                !!!*** C 01 ***!!!

word        kslget(l, wait)                                  /* get a latch */
reg0 ksllt  *l;                                    /* latch we are latching */
    word    wait;                          /* wait for latch or just return */
{
                !!!*** C 02 ***!!!

  reg1 kslla  *state;                                        /* latch state */
  reg2 word    level;                                    /* latching level */

  /* initialize */
                !!!*** C 03 ***!!!

  state = ksuglk(ksugcp());                    /* get process latching state */
  level = l->kslltlvl;                                /* get level of latch */

#ifdef KSLDEBUG
  /* if currently hold a fast latch, cannot get another latch */
                !!!*** C 04 ***!!!

  if (state->ksllalaq)
    ksesic2(OERI(503), ksenrg(state->ksllalaq),
            ksesrgl((text *)kslldt[state->ksllalaq->kslltnum].kslldnam));
#endif

  /* Enforce latch hirearchy to prevent deadlocks.
  * Check if a latch is already held at this level or any higher level.
  */
                !!!*** C 05 ***!!!

  if (bit(state->ksllalow, levelbits[level]))
  {
                !!!*** C 06 ***!!!

    if (!wait)
    {
                !!!*** C 07 ***!!!

      if (!state->ksllalat[level])          /* no latch gotten at this level */
        ;                                    /* allow nowait get to proceded */
      /* allow one duplicate get at a level if it is gotten nowait */
      else if (state->ksllalat[level] != l && !state->ksllalat[KSLLMXLV+1])
        level = KSLLMXLV+1;    /* use the slot that is one past the highest */
      else                            /* never signal conflict on nowait get */
        return FALSE;
    }
    else
      ksesic4(
        OERI(504),              /* kslget: failure to follow lock hierarchy */
        ksenrg(l), ksenrg(state->ksllalow),
        ksenrg(level), ksesrgl((text *)kslldt[l->kslltnum].kslldnam));
  }

  /* set "we are waiting for the latch" and go try to get it */
  state->ksllalaq = l;

  /* Do a fast try to get the latch */

                !!!*** C 08 ***!!!

  if (sclgtf(&l->kslltlat))          /* do the test and set (or equivalent) */
  {
    /* Got the latch on first try */
    bis(state->ksllalow, 1 << level);    /* set level bit for level checking */
    state->ksllalat[level] = l;      /* indicate latch gotten at this level */
    l->kslltefd = kgetfd(ksmgpga);  /* error frame depth for error recovery */

    /* Note that the number of latch gets is used during cleanup (it is not
    *  just for statistics).  So don't delete this code.
    */
    if (wait)
      l->kslltwgt++;                                      /* bump wait gets */
    else
      l->kslltngt++;                                    /* bump nowait gets */

    KSLDBG(state->ksllalaq = (ksllt *)0;)

    /* check if latch debugging is turned on */
    if (ksldbg)
    {
      /* set trace info if appropriate */
      kslsgtr(l, kslcmt);

      /* unprotect the latch's recovery structure if necessary */
      kslprrc(l, TRUE);
    }

    return TRUE;                                          /* return success */
  }
  else if (!wait)    /* if failed to get the latch and not supposed to wait */
  {
    /* Bump nowait attempts. This increment is not protected by the latch,
    * so it may be lost or garbled if several processes do this at the same
    * time.
    */
    l->kslltnfa++;                                        /* nowait failures */
    state->ksllalaq = (ksllt *)0;            /* not trying to get it anymore */
    return FALSE;
  }

  /* Someone else has the latch, we must wait for it.  Call kslges indirectly
  * so the compiler will not inline the routine (this causes many registers
  * to be saved unnecessarily).
  */ 
                !!!*** C 09 ***!!!

  return (*kslger)(l, FALSE);
}


/* remove myself from list of waiter processes on a latch. */
STATICF void kslwrmv(state)
reg0 kslla *state;
{
  reg1 kslla  *wait_proc;
  reg2 kslla **proc_link;

  /* walk list of processes waiting for this latch */

                !!!*** C 10 ***!!!

  for (wait_proc = state->ksllawtr->kslltwkp,
      proc_link = &state->ksllawtr->kslltwkp;
      wait_proc;
      proc_link = &wait_proc->ksllanxw, wait_proc = *proc_link)

                !!!*** C 11 ***!!!

    if (wait_proc == state)                /* if waiter is me */
    {
      *proc_link = state->ksllanxw;                  /* pop myself from list */
      break;
    }

  /* Note that if I was previously killed while linking or unlinking myself
  * from a wait list, I might never have made it on the list, but I would
  * still have my state set as if I did.  We always link on the the waiter
  * list last when adding to the wait list, and unlink first when removing
  * from the wait list.  Therefore I need to clear my state whether I am on
  * the list or not to cleanup from process death.
  */
  state->ksllanxw = (kslla *)0;                            /* no next waiter */
  state->ksllawtr = (ksllt *)0;          /* not on wait list for this latch */
}


/* Second part of kslget.  We failed to get  the latch on the  first try so
* now we have to wait for it.
*/
word  kslges(l, from_macro)
reg0 ksllt  *l;                                    /* latch we are latching */
eword from_macro;                        /* true if called from kslatm macro */
{
  ub4    i;                                                  /* miss counter */

  reg1 kslla  *state;                                        /* latch state */
  reg2 word    level;                                    /* latching level */
  reg3 eword    max_backoff = kslmex;        /* Let's initialize this, okay? */
      eword    other_latch = FALSE;

  /* initialize */
  state = ksuglk(ksugcp());                    /* get process latching state */
  level = l->kslltlvl;                                /* get level of latch */

  /* Don't sleep too long if currently holding a latch since this will tend to
  * backup the people waiting for me.  This does not apply if the latch is
  * an allocated child latch since there are lots of those.
  */
  if (state->ksllalow)                      /* if currently holding a latch */
  {
    for (i = 0; i <= level; i++)            /* for all latches I am holding */
      if (state->ksllalat[i] &&
          !state->ksllalat[i]->kslltchn)      /* if holding non-child latch */
      {
        max_backoff = kslmsl;            /* set max backoff to smaller value */
        other_latch = TRUE;          /* remember we're holding another latch */
        break;
      }
  }

  /* keep trying to get the latch until we succeed */
  for (i = 0; ; i++)
  {
    serc  se;

    /* set "we are waiting for the latch" and go get it */
    state->ksllalaq = l;

    /* try to get the latch again */
    if (sclgts(&se, &l->kslltlat,                        /* the latch to get */
              ksugpi(ksugcp()),                /* the OSD process structure */
              &state->ksllalaq,      /* pointer to latch trying to acquire */
              ksuicl()))                        /* am I the cleanup process */
    {
      l->kslltwgt++;                            /* bump wait gets statistic */
      l->kslltwff++;                  /* bump failed first attempt statistic */
      l->kslltwsl += i;                        /* increment sleeps statistic */
      if (state->ksllalow) l->kslltwth++;  /* increment sleeps holding latch */

      /* increment histogram of wait times */
      if (i >= KSLHSTMAX)
        l->ksllthst[KSLHSTMAX-1]++;
      else l->ksllthst[i]++;   

      if (!from_macro)      /* don't set these if called by fast path macro */
      {
        bis(state->ksllalow, 1 << level);/* set level bit for level checking */
        state->ksllalat[level] = l;  /* indicate latch gotten at this level */

        KSLDBG(state->ksllalaq = (ksllt *)0;)
      }

      l->kslltefd = kgetfd(ksmgpga); /* error frame depth for error recovery */

      /* check if latch debugging is turned on */
      if (ksldbg)
      {
        /* set trace info if appropriate */
        kslsgtr(l, kslcmt);

        /* unprotect the latch's recovery structure if necessary */
        kslprrc(l, TRUE);
      }

      return TRUE;
    }
    else
    {
      /* We did not get the latch, someone else must have it.  We must wait */
      state->ksllalaq = (ksllt *)0;      /* we are not trying to get it now */

      if (SERC_ERROR(se))          /* if something went wrong, signal error */
      {
        (*ksloet)();                                    /* Dump useful info */
        DISCARD ksecrs(&se);                            /* record error code */
        ksesic0(OERI(506));
      }

      if (i == 5 && !ksuicl()) /* if waited for a few hundreth's of a second */
        ksupsx();          /* post cleanup in case dead process holds latch */

      /* if should use post waiters option to latching */

                !!!*** C 12 ***!!!

      if (  kslpwt                                    /* waiting is enabled */
          && l != kslwlst          /* not waiting for the waiter list latch */
          && !from_macro        /* not from macro, macros don't call kslfre */
          && (i == 0 ||                          /* first time through loop */
              !state->ksllawtr)    /* someone woke me but I didn't get latch */
          && !state->ksllalat[kslwlst->kslltlvl]    /* no out of order latch */
          && (kslpwt > 1 ||              /* waiting enabled for all latches */
              kslldt[l->kslltnum].kslldlng))      /* this is a 'long' latch */
      {
        /* Add myself to the head of the waiter list. */
        KSLBEGIN(kslwlst)                    /* get latch waiter list latch */
          /* If I am still on waiter list of a latch that I am holding I need
          * to get off that list before going on another waiter list.  Note
          * that I don't normally take myself off a waiter list until I free
          * the latch to avoid adding extra code path under the latch that
          * people are waiting for.  This is why I could be on a waiter list
          * while I am holding the latch.
          */
          if (state->ksllawtr)              /* if on waiter list for a latch */
            kslwrmv(state);                      /* take myself off the list */

          state->ksllawtr = l;      /* latch whose waiter list I am going on */

          /* give preference to waiters that are holding another latch */
          if (l->kslltwkp                /* if someone already on wait list */
              && !other_latch)              /* and I am not holding a latch */
          {
            /* put myself in second slot of wait list in case the person in
            * the first slot is holding a latch.  This gives him precedence.
            */

            /* people after first guy are now after me */
            state->ksllanxw = l->kslltwkp->ksllanxw;
            l->kslltwkp->ksllanxw = state;          /* I am after first guy */
          }
          else
          {
            /* put myself at the head of the waiter list */
            state->ksllanxw = l->kslltwkp;    /* head of list goes after me */
            l->kslltwkp = state;                    /* I go at head of list */
          }
        KSLEND                                  /* remember I am on the list */
      }

      state->ksllawat = l;                  /* set latch we are waiting for */

      /* do exponential backoff */
      kslewt3(i, max_backoff, (state->ksllawtr ? TRUE : FALSE),
              ksllfe, l, l->kslltnum, i);

      state->ksllawat = (ksllt *)0;        /* clear latch we are waiting for */

      ksucfi();  /* Check for any interrupts which are fatal to the instance */

      ksecss(&se);                                        /* check for error */

      if (i > 7 && ksuicl())              /* if PMON and waited long enough */
      {
        /* PMON has not been able to get the latch.  The latch might be held
        * by a dead process so search for dead processes, and free their
        * latches.  When freeing dead processes latches, PMON must only free
        * latches that have a higher level than the highest level latch he
        * is currently holding since freeing a latch can cause another
        * latch to be gotten which could lead to a conflict with the latches
        * PMON already holds.
        */
        DISCARD ksuxfl();                      /* free dead process' latches */

                !!!*** C 13 ***!!!

        if (i == 200)                          /* if waited for a long time */
        {
          ksupr *pr = kslown(l);            /* process that holds the latch */
          ksdwrf("PMON unable to acquire latch %lx %s\n", (unsigned long)l,
                (char *)kslldt[l->kslltnum].kslldnam);
          if (pr)
            ksdwrf("  possible holder pid = %d ospid=%.*s\n", (int)ksuprp(pr),
                  (int)ksugpri(pr)->ksuospdl, (char *)ksugpri(pr)->ksuospid);
          ksdddt();                                      /* write time stamp */
          ksdfls();                                      /* flush dump file */
          ksdwra("PMON failed to acquire latch, see PMON dump");
        }
      }
    }
  }
}


                oratypes.h
                ==========

/* /v71/d2/713/oracore/public/sx.h */


/*
ORACLE, Copyright (c) 1982, 1983, 1986, 1990 ORACLE Corporation
ORACLE Utilities, Copyright (c) 1981, 1982, 1983, 1986, 1990, 1991 ORACLE Corp

Restricted Rights
This program is an unpublished work under the Copyright Act of the
United States and is subject to the terms and conditions stated in
your  license  agreement  with  ORACORP  including  retrictions on
use, duplication, and disclosure.

Certain uncopyrighted ideas and concepts are also contained herein.
These are trade secrets of ORACORP and cannot be  used  except  in
accordance with the written permission of ORACLE Corporation.
*/


/* $Header: sx.h 7.18 94/04/05 18:34:34 tswang Osd<unix> $ */








#ifndef ORASTDDEF
# include <stddef.h>
# define ORASTDDEF
#endif

#ifndef ORALIMITS
# include <limits.h>
# define ORALIMITS
#endif

#ifndef  SX_ORACLE
#define  SX_ORACLE
#define  SX
#define  ORATYPES


#ifndef TRUE
# define TRUE  1
# define FALSE 0
#endif



#ifdef lint
# ifndef mips
#  define signed
# endif
#endif

#ifdef ENCORE_88K
# ifndef signed
#  define signed
# endif
#endif

#ifdef SYSV_386
# ifndef signed
#  define signed
# endif
#endif





#ifndef lint
typedef          int eword;               
typedef unsigned int uword;               
typedef  signed int sword;               
#else
#define eword int
#define uword unsigned int
#define sword signed int
#endif

#define  EWORDMAXVAL  ((eword) INT_MAX)
#define  EWORDMINVAL  ((eword)      0)
#define  UWORDMAXVAL  ((uword)UINT_MAX)
#define  UWORDMINVAL  ((uword)      0)
#define  SWORDMAXVAL  ((sword) INT_MAX)
#define  SWORDMINVAL  ((sword) INT_MIN)
#define  MINEWORDMAXVAL  ((eword)  32767)
#define  MAXEWORDMINVAL  ((eword)      0)
#define  MINUWORDMAXVAL  ((uword)  65535)
#define  MAXUWORDMINVAL  ((uword)      0)
#define  MINSWORDMAXVAL  ((sword)  32767)
#define  MAXSWORDMINVAL  ((sword) -32767)


#ifndef lint
# ifdef mips
typedef  signed char  eb1;
# else
typedef          char  eb1;               
# endif
typedef unsigned char  ub1;               
typedef  signed char  sb1;               
#else
#define eb1 char
#define ub1 unsigned char
#define sb1 signed char
#endif

#define EB1MAXVAL ((eb1)SCHAR_MAX)
#define EB1MINVAL ((eb1)        0)
#if defined(mips)                   
# ifndef lint
#  define UB1MAXVAL (UCHAR_MAX)
# endif
#endif
#ifndef UB1MAXVAL
# ifdef SCO_UNIX
# define UB1MAXVAL (UCHAR_MAX)
# else
# define UB1MAXVAL ((ub1)UCHAR_MAX)
# endif
#endif
#define UB1MINVAL ((ub1)        0)
#define SB1MAXVAL ((sb1)SCHAR_MAX)
#define SB1MINVAL ((sb1)SCHAR_MIN)
#define MINEB1MAXVAL ((eb1)  127)
#define MAXEB1MINVAL ((eb1)    0)
#define MINUB1MAXVAL ((ub1)  255)
#define MAXUB1MINVAL ((ub1)    0)
#define MINSB1MAXVAL ((sb1)  127)
#define MAXSB1MINVAL ((sb1) -127)

#define UB1BITS          CHAR_BIT
#define UB1MASK              0xff


typedef  unsigned char text;


#ifndef lint
typedef          short    eb2;             
typedef unsigned short    ub2;             
typedef  signed short    sb2;             
#else
#define eb2  short
#define ub2  unsigned short
#define sb2  signed short
#endif

#define EB2MAXVAL ((eb2) SHRT_MAX)
#define EB2MINVAL ((eb2)        0)
#define UB2MAXVAL ((ub2)USHRT_MAX)
#define UB2MINVAL ((ub2)        0)
#define SB2MAXVAL ((sb2) SHRT_MAX)
#define SB2MINVAL ((sb2) SHRT_MIN)
#define MINEB2MAXVAL ((eb2) 32767)
#define MAXEB2MINVAL ((eb2)    0)
#define MINUB2MAXVAL ((ub2) 65535)
#define MAXUB2MINVAL ((ub2)    0)
#define MINSB2MAXVAL ((sb2) 32767)
#define MAXSB2MINVAL ((sb2)-32767)


#ifndef lint
typedef          long  eb4;               
typedef unsigned long  ub4;               
typedef  signed long  sb4;               
#else
#define eb4 long
#define ub4 unsigned long
#define sb4 signed long
#endif

#define EB4MAXVAL ((eb4) LONG_MAX)
#define EB4MINVAL ((eb4)        0)
#define UB4MAXVAL ((ub4)ULONG_MAX)
#define UB4MINVAL ((ub4)        0)
#define SB4MAXVAL ((sb4) LONG_MAX)
#define SB4MINVAL ((sb4) LONG_MIN)
#define MINEB4MAXVAL ((eb4) 2147483647)
#define MAXEB4MINVAL ((eb4)          0)
#define MINUB4MAXVAL ((ub4) 4294967295)
#define MAXUB4MINVAL ((ub4)          0)
#define MINSB4MAXVAL ((sb4) 2147483647)
#define MAXSB4MINVAL ((sb4)-2147483647)


#ifndef lint
typedef unsigned long  ubig_ora;           
typedef  signed long  sbig_ora;           
#else
#define ubig_ora unsigned long
#define sbig_ora signed long
#endif

#define UBIG_ORAMAXVAL ((ubig_ora)ULONG_MAX)
#define UBIG_ORAMINVAL ((ubig_ora)        0)
#define SBIG_ORAMAXVAL ((sbig_ora) LONG_MAX)
#define SBIG_ORAMINVAL ((sbig_ora) LONG_MIN)
#define MINUBIG_ORAMAXVAL ((ubig_ora) 4294967295)
#define MAXUBIG_ORAMINVAL ((ubig_ora)          0)
#define MINSBIG_ORAMAXVAL ((sbig_ora) 2147483647)
#define MAXSBIG_ORAMINVAL ((sbig_ora)-2147483647)




#undef CONST

#ifdef _olint
# define CONST const
#else
#if defined(PMAX) && defined(__STDC__)
#  define CONST const
#else
# ifdef M88OPEN
#  define CONST const
# else
#  ifdef SEQ_PSX_ANSI
#  ifdef __STDC__
#    define CONST const
#  else
#    define CONST
#  endif
#  else
#  define CONST
#  endif
# endif
#endif
#endif



#ifdef lint
# define dvoid void
#else

# ifdef UTS2
#  define dvoid char
# else
#  define dvoid void
# endif

#endif



typedef void (*lgenfp_t)(/*_ void _*/);



#include <sys/types.h>
#define boolean int




#ifdef sparc
# define SIZE_TMAXVAL SB4MAXVAL             
#else
# define SIZE_TMAXVAL UB4MAXVAL           
#endif

#define MINSIZE_TMAXVAL (size_t)65535


#endif

萝卜治咳嗽 简单有奇效

| 6 Comments

  用萝卜治疗宝宝咳嗽比较简单而且效果奇好,并且没有副作用,宝宝也比较容易接受。用萝卜治疗宝宝咳嗽可以说是一种不可多得的好方法。根据网友反应,这种方法见效比较快,效果也很好。

  方法一:萝卜榨汁,再加上些蜂蜜,搅拌均匀后饮用。

  方法二:听把萝卜挖个洞,放几颗冰糖,竖着塞在米桶里,过一夜,萝卜洞里都是水,把水稍温下 ,给宝宝喝,效果很好。

  方法三:挑选一些新鲜的、水分较多的白萝卜洗净,切片或切丝,加白糖适量拌匀,放一小时后取其汁饮用。早晚各服半杯,连服三天。

  方法四:白萝卜约一斤重,洗净,连皮切薄片,冰糖四两(可分三回用),清水五饭碗一起放锅里用文火炖煮,煮到剩约三碗水时可关掉火。冬天时要吃热的,夏天温或凉的均可(但不要冰),每天当开水喝,接连喝二、三天,一定有效。

  方法五:将白萝卜洗净,控干水后切成0.5厘米厚的圆形薄片。取10片切好的白萝卜放在碗里,把5块关东糖掰成一些小块,分别放在白萝卜的中间和上面,盖上盖。几小时后,用干净的筷子取出白萝卜片(看上去已空心),将汁液服下。每日3次,坚持一周咳嗽便可痊愈。

  方法六:准备等量的麦芽糖和萝卜,先将萝卜切成小片(以能装进瓶中为宜)与麦芽糖一起置于瓶内。萝卜汁会渐渐渗出,取汁饮用即可。麦芽糖有润喉作用,萝卜富含维生素C,这是萝卜汁加麦芽糖能有效镇咳的主要原因。

  方法七:萝卜用榨汁机榨出近300ML的萝卜汁,放一块冰糖(约大拇指大),放在锅里刚刚煮开就行下,放在冰箱里,每天早晚热温了喝50ML,基本上就好了。

小儿肺炎与气管炎的辨别法

| 9 Comments

上呼吸道感染(感冒)是婴儿的常见病。虽然大部分患难与共儿能够痊愈,但有时由于家长的疏忽,也会使用权感冒发展成气管炎以至肺炎。肺炎是婴儿期死亡率较高的一种疾病。必须及早诊断和治疗。气管炎和肺炎的常见症状都是发热、咳嗽和呼吸加快。那么,怎样来辨别这两种疾病呢?

  一种简易的方法是用计数的方法算出孩子的呼吸频率,根据孩子的呼吸频率来辨别。当孩子安静时或入睡后,计算孩子一分钟的呼吸频率。呼吸增快的标准是:

  •   1-2个月婴儿:呼吸频率大于或等于每分钟60次;
  •   2个月-1岁婴儿:呼吸频率大于或等于每分钟50次
  •   1-3岁婴儿:呼吸频率大于或等于每分钟40次

  如果婴儿的呼吸次数低于上述标准,只是咳嗽和发热,一般可诊断为气管炎。如果连续两次测定,婴儿的呼吸频率达到或高于上述标准,基本上可判定为肺炎。此时,应立即将孩子送往医院,及时治疗。

正常体温、高烧与低烧

| 8 Comments
体温是指机体内部的温度。正常人腋下温度为30~37度,口腔温度比腋下高0.2~0.4度,直肠温度又比口腔温度高0.3~ 0.5度。

人体的温度是相对恒定的正常人在24小时内体温略有波动,但是一般相差不超过1度
生理状态下,早晨体度略低,下午略高。运动、进食后、妇女月经期前或妊娠期体温稍高,而老年人体温偏低。

体温高于正常称为发热,37.5~38度为低热,38~39度为中度发热,39~40度为高热,40度以上为超高热
人体温度相对恒定是维持人体正常生命活动的重要条件之一,如体温高于41度或低于25度时将严重影响各系统(特别是神经系统)的机能活动,甚至危害生命。机体的产热和散热,是受神经中枢调节的,很多疾病都可使体温正常调节机能发生障碍而使体温发生变化。临床上对病人检查体温,观罕其变化对诊断疾病或判断某些疾病的预后有重要意义。

腋温34.7-37.3
口温35.5-37.5
肛温36.6-38
耳温35.8-38

淋巴细胞正常百分比参考值是20--40%。其比率通常称为LYM%或者LYMPH%、

淋巴细胞是一种免疫细胞,当绝对值高时,人体的免疫力就会低下,这个时期很容易感染一些疾病。

引起淋巴细胞高的原因常见于病毒性的传染病如流感,需要注意的是要增强免疫力机能;至于用药方面不能盲目服用,如果在本身不知的情况下服用某些过敏性药物也会致使淋巴细胞增高,所以要遵医嘱,正确的认知才可以积极预防疾病。

引起淋巴细胞百分比偏高原因很多,如总白细胞数目下降,或淋巴细胞数目增多。常见于某些病毒性感冒,自身免疫性疾病,一些药物的副作用等,临床还要考虑其他项目指标。

淋巴细胞白血病是骨髓及其他造血组织中有广泛的白血病细胞异常增生,主要是不成熟淋巴细胞,及浸润其他组织器官,导致正常造血功能衰竭,表现为正常造血细胞显著减少。与淋巴细胞百分比偏高有关系。确诊需做骨髓穿刺,检查骨髓象。
爱心提示:不排除药物副作用引起。

小儿咳嗽多痰的药膳调理

| 7 Comments

咳嗽是小儿呼吸道疾病的常见症状之一,现代医学的急、慢性支气管炎、气管炎、部分咽喉炎均属于此病范围。中医学按其临床主要症状将咳嗽分为两大类,一般继发于感冒之后的称为"外感咳嗽",没有明显感冒症症的称为"内伤咳嗽"。小儿咳嗽除了要遵医嘱服药外,饮食要清淡、易消化,忌食腥荤辛辣之品。此外,可用下述药膳辅助治疗。
1、风寒咳嗽:特点是咳嗽,咽痒,咳痰清稀,鼻塞疏清涕等,治疗宜宣肺散寒止咳。
      (1)紫苏粥:紫苏叶10克,粳米50克,生姜3片,大枣3枚。先用粳米煮粥,粥将熟时加入苏 叶、生姜、大枣,趁热服用。
      (2)葱白粥:大米50克,生姜5片,连须葱白5段,米醋5毫升,加水适量煮粥,趁热饮用。
      (3)杏仁萝卜煎:杏仁(甜)10克,生姜3片,白萝卜100克,水煎服,每日1剂。
      (4)核桃生姜饮:核桃肉5枚捣烂,生姜汁适量送服。
      (5)家庭常备中成药:通宣理肺丸。橘红丸、橘红痰咳液等。

2、风热咳嗽:特点是咳嗽,痰黄黏稠,鼻流浊涕,咽红口干等。治宜疏风清热,化痰止咳
      (1)二汁饮:鲜藕汁、梨汁等份,生服。
      (2)萝卜冰糖汁:白萝卜取汁100~200毫升,加冰糖适量隔水炖化,睡前1次饮完,连用3~5 次。

  (3)葱白梨汁:葱白连须7根,梨1个,冰糖适量,水煎服。

  (4)丝瓜花蜜饮:洁净丝瓜花10克,放入瓷杯内,以沸水冲泡,盖盖焖浸10分钟,再调入蜂 蜜适量,趁热顿服。

  (5)橄榄萝卜饮:橄榄400克,萝卜500~1000克,煎汤代茶饮。

  (6)蜂蜜萝卜汁:白皮萝卜1个,洗净,挖空中心,将蜂蜜100克装入,置大碗内,加水蒸熟 服。

  (7)红皮萝卜洗净(不去皮),切碎后加入麦芽糖2~3匙,搁置一夜,将溶成的萝卜糖水频频 饮服。

  (8)牛蒡粥:鲜牛蒡根研碎滤取汁100毫升,粳米50克,共煮粥,趁热服。

  (9)家庭常备中成药:急支糖浆、复方甘草合剂、银黄口服液等。

  3、痰温咳嗽:特点是咳嗽痰多,痰液清稀,早晚咳重,常伴有食欲不振、口水较多等症。 治宜燥湿化痰。

  (1)橘皮粥:鲜橘皮30克,洗净,切丝,大米100克,加水煮粥。

  (2)薏仁粥:薏苡仁50克,粳米100~200克,共煮成粥,常饮服。

  (3)二陈二仁粥:陈皮9克,半夏6克,茯苓12克,薏仁15克,冬瓜仁15克,粳米100克。前五 料水煎,沸后约10分钟,去滓取汁。加粳米及适量水,同煮为粥。

  (4)薏米杏仁粥:薏米50克,杏仁(去皮尖)10克。薏米洗净,加水煮成半熟,放入杏仁,粥 成加少许白糖。

  (5)柚皮饮:柚子皮适量,水煎服。

  (6)常备中成药:橘红丸、橘红痰咳液等。
 4、痰热咳嗽:咳嗽,吐黄痰,伴口渴、唇红、尿黄、便干等症。治宜清热化痰。

  (1)荸荠海蜇饮:荸荠200克,海蜇皮100克,水煎,分服。

  (2)秋梨白藕汁:秋梨去皮、核、白藕去节,各等量,切碎,取汁,频服。

  (3)芦根粥:鲜芦根150克,竹茹15克,生姜3克,粳米50克。先煎前二味药取汁,入米煮粥 ,待熟时加生姜,稍煮即可。

  (4)杏仁糖:带皮苦杏仁、冰糖各等份,研碎混合,刺成杏仁糖,早服各冲服3克。

  (5)核桃仁150克,冰糖200克,山楂50克。先将核桃仁水浸糜成浆,再将山楂熬成汁,去滓 ,入冰糖及核桃浆同煮熟。随意食。

  (6)冬瓜子15克,加红糖少许,捣烂后开水冲服,一日2次。

  (7)常备中成药:急支糖浆、先声咳喘宁、复方鲜竹沥、鲜竹沥等。

  5、气虚咳嗽:特点是咳嗽日久不愈,咳声无力,痰液清稀,面白多汗等。治宜健脾益气, 补肺止咳。

  (1)豆腐煲:豆腐250克,红糖50克,生姜5片,慢火煲1小时,每晚睡前食用,连服1周。

  (2)杏仁、萝卜、猪肺汤:猪肺、白萝卜各1个(切块),杏仁9克,共炖烂熟食。

  (3)海带根500克,生姜75克,红糖适量。加水熬成450毫升的浓缩糖浆,每次15毫升,日3次 ,10在为一疗程。

  (4)黄芪粥:黄芪20克,粳米50克。黄芪加水500毫升,煮至200毫升,去滓。入淘净粳米, 加水煮至粥成。温热顿服。

  (5)猪肺薏仁粥:薏米150克,猪肺1个,切丁,共煮成粥。

  (6)花生红枣汤:花生米、大枣、蜂蜜各30克,水煎。食花生、枣,喝汤。日2次。

  (7)常备中成药:儿康宁、四君子合剂。

  6、阴虚咳嗽:特点是干咳少痰,咳久不愈,常伴形体消瘦、口干咽燥、手足心热等症。治 宜滋阴润肺止咳。

  (1)门冬粥:天门冬15~20克,粳米60克,冰糖少许。先煎天门冬取汁去滓,入粳米同煮为 粥、粥成加入冰糖。每日早起空腹服用。

  (2)银耳粥:银耳25克,粳米100克。冰糖适量。银耳加水煮至六成熟,入米共煮成粥,直锅 前加冰糖。

  (3)百合粳米粥:百合50克,粳米100克,红枣5~10枚,赤子豆30克,白糖适量,先将红小 豆煮至半熟,入粳米、百合、红枣同煮为粥,粥成后加入白糖。

  (4)川贝酿梨:川贝母12克,雪梨6个,冬瓜条100克,冰糖100克,糯米100克,白矾3克。先将糯米蒸熟,冬瓜条切成小颗粒,川贝研成末,白矾溶于水;再将雪梨去皮,切下盖,挖出梨核,浸入白矾溶液中以防变色;制作时取出梨,在沸水中烫一下,冲凉,放碗内,将糯米饭、冬瓜条粒、冰糖拌匀,和入川贝粉,装雪梨内,盖好,蒸1小时至烂即成;另将剩下的 冰糖溶水,收浓汁,淋在刚出笼的梨上。每早晚各吃梨1个。

  (5)川贝冰糖梨:川贝粉3克,大梨1个,冰糖6克。将梨去皮,挖去梨心,填入川贝粉、冰糖 ,蒸熟食之。

  (6)蜂蜜蒸梨(萝卜):梨或白萝卜1个,挖空心,蜂蜜30克装入梨或萝卜内,蒸熟食用,每日 2个。

  (7)黑芝麻60克,核桃仁60克,冰糖50克,共捣烂,开水冲服,每次10~15克,早晚空腹服 。尤其适用于伴阴虚肠燥便秘者。

  (8)百合猪肺汤:百合30克,猪肺250克。共慢火炖熟,加少许食盐调味,饮汤食猪肺。

  (9)银耳鸭蛋:银耳9克,先煮;鸭蛋1枚,打入银耳汤,加入适量冰糖调味食用。

  (10)家庭常备中成药:养阴清肺丸、念慈庵川贝枇杷膏等。

Pages

Powered by Movable Type 6.3.2

About this Archive

This page is an archive of entries from August 2008 listed from newest to oldest.

July 2008 is the previous archive.

September 2008 is the next archive.

回到 首页 查看最近文章或者查看所有归档文章.