<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
   <channel>
      <title>eygle&apos;s digest</title>
      <link>http://www.eygle.com/digest/</link>
      <description>eygle的网摘,网摘来自网络,仅代表本人关注内容,不代表本人观点,如有侵权,请来信告知,即刻删除.</description>
      <language>en</language>
      <copyright>Copyright 2008</copyright>
      <lastBuildDate>Mon, 25 Aug 2008 17:35:52 +0800</lastBuildDate>
      <generator>http://www.sixapart.com/movabletype/</generator>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs> 

      
      <item>
         <title>Compare-and-swap</title>
         <description><![CDATA[from <a href="http://en.wikipedia.org/wiki/Compare_and_swap">Wikipedia</a>
<strong>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. </strong>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.]]></description>
         <link>http://www.eygle.com/digest/2008/08/compare-and-swap.html</link>
         <guid>http://www.eygle.com/digest/2008/08/compare-and-swap.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Oracle摘</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Oracle</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">sicence</category>
        
         <pubDate>Mon, 25 Aug 2008 17:35:52 +0800</pubDate>
      </item>
      
      <item>
         <title>Basics of C within the Oracle kernel</title>
         <description><![CDATA[出处:<br>
http://www.oraclefans.cn/forum/showtopic.jsp?rootid=3530&CPages=1<br>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
<br />
C is a function based language and as with most languages is composed of<br />
declarations and statement blocks.<br />
<br />
Below is a very simple example and even this example uses 5 functions:<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; strcat(),strcpy(),write(),strlen() and print_string().<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ***************<br />
<br />
char text_string[100];<br />
<br />
print_string()<br />
{<br />
char output_string[100];<br />
<br />
strcpy(output_string,"C is a wonderful language"); /* Copy string */<br />
<br />
strcat(output_string,text_string);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* Concatentate string */<br />
<br />
if (write(1,output_string,strlen(output_string))&lt;0)/* Write output */<br />
&nbsp; &nbsp; return false;<br />
else<br />
&nbsp; &nbsp; return true;<br />
}<br />
<br />
main()<br />
{<br />
&nbsp; strcpy(text_string," but C++ is better still");<br />
<br />
&nbsp; if (!print_string())<br />
&nbsp; &nbsp;  /* error handling */<br />
&nbsp; &nbsp;  ;<br />
}<br />
<br />
An equivalent in pl/sql would be :<br />
<br />
declare<br />
<br />
text_string&nbsp; &nbsp;  varchar(100);<br />
<br />
function print_string return boolean<br />
as<br />
&nbsp; &nbsp;  output_string varchar(100);<br />
&nbsp;  begin<br />
&nbsp; &nbsp;  output_string := 'C is a wonderful language';<br />
<br />
&nbsp; &nbsp;  output_string := output_string || text_string;<br />
<br />
&nbsp; &nbsp;  dbms_output.put_line(output_string);<br />
<br />
&nbsp; &nbsp;  return true;<br />
&nbsp;  end;<br />
<br />
begin<br />
<br />
&nbsp;  text_string := ' but C++ is better still';<br />
<br />
&nbsp;  if (not print_string)<br />
&nbsp;  then<br />
&nbsp; &nbsp; &nbsp; &nbsp; /* Error handling */<br />
&nbsp; &nbsp; &nbsp; &nbsp; null;<br />
&nbsp;  end if;<br />
<br />
end;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ***************<br />
<br />
Rather than just document the basic C commands , I have taken one<br />
particular kernel module (ksl) and highlighted the most<br />
significant C commands and Oracle coding techniques.<br />
<br />
I have avoided adding my own comments to the source files as these would<br />
get lost among the numerous coding comments. Instead I have added markers<br />
against which detailed notes are provided below.<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; Header file marker : !!*** H xx ***!!!<br />
&nbsp; &nbsp; &nbsp; &nbsp; Source file marker : !!*** C xx ***!!!<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; Notes to the extract from ksl.h<br />
&nbsp; &nbsp; &nbsp; &nbsp; ===============================<br />
<br />
ksl.h&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  - Kernel Service Locking.<br />
=====<br />
<br />
In general header files are used for the main declarations.<br />
<br />
Comments&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 01 ***!!!<br />
--------<br />
<br />
As in pl/sql, comments begin with /* and end with */ .<br />
<br />
Compile time directives&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** H 02 ***!!!<br />
-----------------------<br />
<br />
Commands which are pre-processed by the compiler start with #.<br />
<br />
Conditional compilation&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** H 02 ***!!!<br />
-----------------------<br />
<br />
To conditionally compile code you use the #ifdef / #ifndef directive.<br />
<br />
In kernel header files there will be a list of other header files to be<br />
included. The #ifndef is used to prevent a header file being included twice.<br />
<br />
Including other source/header files&nbsp; &nbsp;  !!!*** H 02 ***!!!<br />
-----------------------------------<br />
<br />
To include header and/or source files you use the compile time<br />
directive #include. Include files can be nested to many levels.<br />
<br />
PUBLIC TYPES AND CONSTANTS&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 03 ***!!!<br />
--------------------------<br />
<br />
All declarations between<br />
&nbsp; &nbsp; &nbsp; &nbsp; /* PUBLIC TYPES AND CONSTANTS */<br />
&nbsp; &nbsp; and<br />
&nbsp; &nbsp; &nbsp; &nbsp; /* PRIVATE TYPES AND CONSTANTS */<br />
<br />
are available to other layers within the kernel.<br />
<br />
The 'define' preprocessor command&nbsp; &nbsp; &nbsp;  !!!*** H 04 ***!!!<br />
---------------------------------<br />
<br />
The define command is used to create macros which are then expanded by the<br />
preprocessor.<br />
<br />
This command is used extensively throughout the kernel and its use ranges<br />
from defining maximum values through to complete code segments.<br />
<br />
In general if an identifier is in uppercase then it represents a macro.<br />
<br />
Function declarations&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** H 05 ***!!!<br />
---------------------<br />
<br />
For ANSI compliance , public functions are declared within the header files.<br />
<br />
word&nbsp; &nbsp;  kslget(/*_ struct ksllt *id, word wait _*/);<br />
<br />
&nbsp; where&nbsp;  word&nbsp; - the datatype of the return value from the function.<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; kslget- function name, max 6 characters.<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (/*_ xxx,yyy, _*/)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - xxx,yyy - arguments for function.<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /*_ _*/&nbsp;  - used by olint to check that this function is<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; being called with the correct number of arguments.<br />
<br />
Using defines to represent functions&nbsp; &nbsp; !!!*** H 06 ***!!!<br />
------------------------------------<br />
<br />
It is often the case that functions are replaced by macros , mainly<br />
for performance - inline code is faster than function calls.<br />
<br />
Using defines to represent code segments !!!*** H 07 ***!!!<br />
----------------------------------------<br />
<br />
Datatypes&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 08 ***!!!<br />
---------<br />
<br />
C variables can be simple or complex (records) and either a scalar or an array.<br />
<br />
The typedef command is crucial to the understanding of variable declarations.<br />
Throughout the kernel, no reference is ever made to the basic C types such<br />
as int or char. Instead all the C types are 'aliased' via the typedef command.<br />
<br />
&nbsp;  e.g.&nbsp; &nbsp; typedef unsigned int ub4<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  ub4 my_integer;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; is equivalent to<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  unsigned int my_integer;<br />
<br />
The importance of typedef for the C datatypes cannot be overstated - any<br />
developer who used the C datatypes directly would have a very short career.<br />
The cornerstone of portability is the correct use of datatypes.<br />
<br />
See oratypes.h for a complete list of the 'aliases' for the C datatypes.<br />
<br />
Records&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** H 08 ***!!!<br />
-------<br />
<br />
In C, records are called structures and are declared with the 'struct'<br />
command.<br />
<br />
Refering to struct ksllt:<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; ub4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  kslltwgt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Simple variable.<br />
&nbsp;  ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; struct ksllt *kslltchn;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Pointer to record.<br />
&nbsp;  ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; ub4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  ksllthst[KSLHSTMAX]; Simple variable array.<br />
<br />
Pointers and pointers to functions&nbsp; &nbsp; &nbsp; !!!*** H 09 ***!!!<br />
----------------------------------<br />
<br />
For those unfamiliar to C , one of the hardest concepts to grasp is<br />
the notion of pointers.<br />
<br />
Instead of declaring a variable and its storage area, you can declare<br />
a variable which points to the memory area where the data is actually<br />
stored. This data could be an integer number, a text string and most<br />
importantly of all a function.<br />
<br />
A variable is declared a pointer by prefixing '*' to the identifier name.<br />
<br />
The use of pointers and pointers to functions is fundamental not only to<br />
the Oracle kernel but to most software written in C.<br />
<br />
Refering to struct&nbsp;  kslld :<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; text&nbsp;  *kslldnam;&nbsp; &nbsp; &nbsp;  Pointer to a text string which contains<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; the latch name ( v$latchname ).<br />
&nbsp; &nbsp;  ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; void&nbsp; (*kslldcln)(/*_ word action, ksllt *lp _*/);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Pointer to a function for latch cleanup.<br />
<br />
<br />
Notifiers&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** H 10 ***!!!<br />
---------<br />
<br />
Each layer within the kernel has a notifier function used during<br />
instance startup.<br />
<br />
Registration defines&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 11 - H 15 ***!!!<br />
--------------------<br />
<br />
There are numerous registration defines which are processed by other<br />
kernel modules in order to build a single data structure to represent<br />
information registered by different kernel layers - e.g. init.ora parameters.<br />
<br />
&nbsp; SGA variables&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** H 11 ***!!!<br />
<br />
&nbsp; PGA variables&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** H 12 ***!!!<br />
<br />
&nbsp; Events&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 13 ***!!!<br />
<br />
&nbsp; X$ tables&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** H 14 ***!!!<br />
<br />
&nbsp; init.ora parameters&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** H 15 ***!!!<br />
<br />
Apart from X$ tables, the #define which preceeds the KSP registration is the<br />
one used within the source and not the _ identifier.<br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; Notes to the extract from ksl.c<br />
&nbsp; &nbsp; &nbsp; &nbsp; ===============================<br />
<br />
ksl.c&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  - Kernel Service Locking.<br />
=====<br />
<br />
Function Definition&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** C 01 ***!!!<br />
-------------------<br />
<br />
A function starts with its name and argument list, followed by a<br />
declaration of the argument types.<br />
<br />
Local Variable declarations&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** C 02 ***!!!<br />
---------------------------<br />
<br />
Variables only available within this function.<br />
<br />
Variables are in fact declared at the start of a statement block, so<br />
it is possible to have nested declarations.<br />
<br />
i.e.&nbsp; func(a)<br />
&nbsp; &nbsp; &nbsp; int a;<br />
&nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; int b;<br />
&nbsp; &nbsp; &nbsp; &nbsp; b=1;<br />
&nbsp; &nbsp; &nbsp; &nbsp; { int b;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b=1;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { int b;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b=1;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; }<br />
<br />
The normal rules of scope apply - inner declarations have precedence<br />
over outer.<br />
<br />
Assignments&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** C 03 ***!!!<br />
-----------<br />
<br />
In C, the assignment operator is =, which is one of the main<br />
causes of coding error as you would normally expect this operator<br />
to represent equality.<br />
<br />
Raising internal (600) errors&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** C 04 ***!!!<br />
-----------------------------<br />
<br />
Within the kernel, ora-600 errors are identified by the wrapper<br />
OERI() and are raised by either the ksesic() or ASSERT() functions.<br />
<br />
Raising Oracle Errors.<br />
---------------------<br />
<br />
Oracle error numbers are identified by the wrapper OER() and are<br />
raised by the ksesec() functions.<br />
<br />
The use of the OER() wrapper is not guaranteed within pl/sql.<br />
<br />
Checking for Events<br />
-------------------<br />
<br />
The ksepec() function is passed one argument, an OER() number, and<br />
returns the current level number. If level number is zero then this<br />
event has not been set.<br />
<br />
Bit manipulation&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 05 ***!!!<br />
----------------<br />
<br />
Bit functions are used to test,set and clear bits.<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; bit()&nbsp;  - test<br />
&nbsp; &nbsp; &nbsp; &nbsp; bis()&nbsp;  - set<br />
&nbsp; &nbsp; &nbsp; &nbsp; bic()&nbsp;  - clear.<br />
<br />
These functions are in fact macros.<br />
<br />
Conditional Evaluation&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 06 ***!!!<br />
----------------------<br />
<br />
The control statements such as 'if', 'for' and 'while' have no<br />
equivalent end statement such as 'endif'. They control the execution<br />
of the next statement block.<br />
<br />
Pointer referencing&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** C 07 ***!!!<br />
-------------------<br />
<br />
Pointer referencing of structure ( record ) variables is done<br />
with the '-&gt;' operator.<br />
<br />
Address parameters&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 08 ***!!!<br />
------------------<br />
<br />
The '&amp;' operator before a variable passes the address of the<br />
variable to sclgtf() .<br />
<br />
Operating System Dependent (OSD) routines&nbsp; &nbsp; &nbsp;  !!!*** C 08 ***!!!<br />
-----------------------------------------<br />
<br />
In general osd routines begin with the letter s.<br />
<br />
Calling a function via a pointer&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 09 ***!!!<br />
--------------------------------<br />
<br />
The function call (*kglger)() is an example of calling a<br />
function indirectly. The function actually being called is kslges().<br />
<br />
'for' control loop&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 10 ***!!!<br />
------------------<br />
<br />
One of the most common control structures used in C.<br />
<br />
The 'for' control statement contains an initial expresion,<br />
an evaluation expression and a next iteration expression.<br />
<br />
If the evaluation is true then the enclosing statement block<br />
is executed.<br />
<br />
i.e. for (i=0;i&lt;10;i++)<br />
&nbsp; &nbsp; &nbsp;  { printf("The value of i is %d\n",i); }<br />
<br />
<br />
To terminate the loop, you can use the break statement .<br />
<br />
To branch back to the control expression, you can use the continue<br />
statement.<br />
<br />
Equality operator&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** C 11 ***!!!<br />
-----------------<br />
<br />
The equality operator is '==' and NOT '='.<br />
<br />
And / Or operators&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 12 ***!!!<br />
------------------<br />
<br />
The 'and' operator is '&amp;&amp;', the 'or' operator '||'.<br />
<br />
e.g. pl/sql :&nbsp; if ( test_value = 10 or ( a = 5 and b = 6 ) )<br />
<br />
&nbsp; &nbsp;  becomes in C :<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  if ( test_value == 10 || ( a ==5 &amp;&amp; b == 6 ))<br />
<br />
Output to trace and alert files&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  !!!*** C 13 ***!!!<br />
-------------------------------<br />
<br />
ksdwrf() function : write to trace file.<br />
<br />
ksdwra() function : write to alert file.<br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Extract from ksl.h<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ==================<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 01 ***!!!<br />
/*<br />
* $Header: ksl.h,v 1.44.710.5 94/07/07 11:58:37 ksriniva: Exp $ ksl.h<br />
*/<br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 02 ***!!!<br />
<br />
#ifndef&nbsp; SE<br />
#include &lt;se.h&gt;<br />
#endif<br />
#ifndef&nbsp; SC<br />
#include &lt;sc.h&gt;<br />
#endif<br />
#ifndef&nbsp; SM<br />
#include &lt;sm.h&gt;<br />
#endif<br />
#ifndef&nbsp; SP<br />
#include &lt;sp.h&gt;<br />
#endif<br />
#ifndef&nbsp; SLO<br />
#include &lt;slo.h&gt;<br />
#endif<br />
#ifndef&nbsp; KSM<br />
#include &lt;ksm.h&gt;<br />
#endif<br />
#ifndef&nbsp; KGSL<br />
#include &lt;kgsl.h&gt;<br />
#endif<br />
#ifndef&nbsp; KQF<br />
#include &lt;kqf.h&gt;<br />
#endif<br />
#ifndef KSP<br />
#include &lt;ksp.h&gt;<br />
#endif<br />
#ifndef&nbsp; KSD<br />
#include &lt;ksd.h&gt;<br />
#endif<br />
#ifndef&nbsp; KSE<br />
#include &lt;kse.h&gt;<br />
#endif<br />
#ifndef KVI<br />
#include &lt;kvi.h&gt;<br />
#endif<br />
<br />
#ifndef&nbsp; KSL<br />
#define&nbsp; KSL<br />
<br />
/***********/<br />
/* LATCHES */<br />
/***********/<br />
<br />
/* Set KSLDEBUG to debug systems that hang waiting for latches that no one<br />
* is holding.&nbsp; This can happen if someone does a fast latch get and then<br />
* exits the block and gets another latch.<br />
*/<br />
/* #define KSLDEBUG 1 */<br />
<br />
#ifdef KSLDEBUG<br />
#&nbsp; define KSLDBG(exp) exp<br />
#else<br />
#&nbsp; define KSLDBG(exp)<br />
#endif<br />
<br />
<br />
<br />
/* A latch is a type&nbsp; of&nbsp; lock that can be&nbsp; very quickly acquired and freed.<br />
* Latches are&nbsp; typically used to&nbsp; &nbsp; prevent&nbsp; more&nbsp;  than one process&nbsp;  from<br />
* executing the same&nbsp; piece of&nbsp; code at&nbsp; a given time.&nbsp; Contrast&nbsp; this with<br />
* enqueues&nbsp; which&nbsp; are usually&nbsp; used to prevent&nbsp; more than one process from<br />
* accessing the same data structure at a given&nbsp; time.&nbsp; Associated with each<br />
* latch is a cleanup procedure that will be called if a process&nbsp; dies while<br />
* holding&nbsp; the latch.&nbsp; Latches&nbsp; have an&nbsp; associated level&nbsp; that&nbsp; is used to<br />
* prevent deadlocks.&nbsp; Once a process acquires a latch at a certain level it<br />
* cannot subsequently acquire a latch at a&nbsp; level that is equal to&nbsp; or less<br />
* than that level (unless it acquires it nowait).<br />
*/<br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 03 ***!!!<br />
<br />
/* PUBLIC TYPES AND CONSTANTS */<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 04 ***!!!<br />
<br />
#define KSLMXLATCH 60 K_MLSIF(+6)<br />
&nbsp; /** maximum number of latches.&nbsp; To increase, just&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  **<br />
&nbsp;  ** change, recompile ksmp.c and ksl.c.&nbsp; This could be eliminated, but it **<br />
&nbsp;  ** doesn't seem worth the extra code.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; */<br />
<br />
/* the pointer to the latch object (ksllt) is public */<br />
<br />
/* PUBLIC PROCEDURES */<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 05 ***!!!<br />
<br />
word&nbsp; &nbsp;  kslget(/*_ struct ksllt *id, word wait _*/);<br />
&nbsp;  /*<br />
&nbsp;  ** Get the latch specified by "id",&nbsp; on&nbsp; behalf&nbsp; of&nbsp; the&nbsp; current<br />
&nbsp;  ** session.&nbsp; If "wait" is FALSE, return immediately if the&nbsp; latch<br />
&nbsp;  ** is in use; if TRUE, keep trying and return when the latch&nbsp; has<br />
&nbsp;  ** been granted.&nbsp; Return TRUE&nbsp; if&nbsp; and&nbsp; only&nbsp; if&nbsp; the&nbsp; latch&nbsp; was<br />
&nbsp;  ** granted. <br />
&nbsp;  **<br />
&nbsp;  ** In order to&nbsp;  prevent deadlocks,&nbsp;  this procedure checks&nbsp;  for<br />
&nbsp;  ** errors in latch&nbsp;  sequence based on&nbsp; level.&nbsp;  Once&nbsp; a&nbsp; process<br />
&nbsp;  ** acquires a latch at a certain level it&nbsp; cannot acquire another<br />
&nbsp;  ** latch at&nbsp; a level less&nbsp; than or equal to&nbsp; that level.&nbsp; There are<br />
&nbsp;  ** two exceptions to this rule.&nbsp; One, a process may acquire a latch<br />
&nbsp;  ** at any level if it has not acquired a latch at that level and<br />
&nbsp;  ** it acquires the latch nowait.&nbsp;  Two, a process may acquire<br />
&nbsp;  ** exactly one duplicate latch (latch at the same level as another<br />
&nbsp;  ** latch) if it acquires it nowait.<br />
&nbsp;  **<br />
&nbsp;  ** This routine will&nbsp; raise an error if&nbsp; called&nbsp; during&nbsp; cleanup,<br />
&nbsp;  ** with "wait" equal to TRUE, and the latch is busy.&nbsp; This is so<br />
&nbsp;  ** PMON does not get stuck acquiring a latch.<br />
&nbsp;  */<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 06 ***!!!<br />
<br />
/* word kslgetd(struct ksllt *lt, word wait, CONST char *comment); */<br />
#define kslgetd(lt, wait, comment) ((kslcmt = (comment)), kslget((lt), (wait)))<br />
&nbsp;  /*<br />
&nbsp;  ** NEW: kslgetd() is the new debugging version of kslget().&nbsp; It takes<br />
&nbsp;  ** an additional comment string as an argument.&nbsp; If the latch trace<br />
&nbsp;  ** event (currently event # 10005) is turned on, this comment is<br />
&nbsp;  ** associated with the latch.&nbsp; If a latch hierarchy error occurs later<br />
&nbsp;  ** on while this latch is still held, the latch dump routines will also<br />
&nbsp;  ** print the relevant comment strings.<br />
&nbsp;  ** Warning: the comment string must persist for the lifetime of the PGA;<br />
&nbsp;  ** ideally, it should be a literal constant.<br />
&nbsp;  */<br />
<br />
<br />
void&nbsp; &nbsp;  kslfre(/*_ struct ksllt *id _*/);<br />
&nbsp;  /*<br />
&nbsp;  ** Free the latch specified by "id", on&nbsp; behalf&nbsp; of&nbsp; the&nbsp; current<br />
&nbsp;  ** session.<br />
&nbsp;  */<br />
<br />
/* void kslfred(struct ksllt *lt, CONST char *comment); */<br />
#define kslfred(lt, comment) ((kslcmt = (comment)), kslfre((lt)))<br />
&nbsp;  /*<br />
&nbsp;  ** NEW: kslfred() is the new debugging version of kslfre().&nbsp; It takes<br />
&nbsp;  ** an additional comment string as an argument.&nbsp; If the latch trace<br />
&nbsp;  ** event (currently event # 10005) is turned on, this comment is<br />
&nbsp;  ** associated with the latch.&nbsp; If a later attempt is made to free this<br />
&nbsp;  ** latch before it is gotten again, the latch dump routines will also<br />
&nbsp;  ** print the relevant comment strings.<br />
&nbsp;  ** Warning: the comment string must persist for the lifetime of the PGA;<br />
&nbsp;  ** ideally, it should be a literal constant.<br />
&nbsp;  */<br />
<br />
<br />
/* Fast latching macros.&nbsp; These macros can be used to very quickly get and<br />
* free a latch. The KSLBEGIN macro gets the latch (in wait mode) and the<br />
* KSLEND macro frees the latch.&nbsp; The code in between the two macros executes<br />
* with the latch held.<br />
*<br />
* The code between the KSLBEGIN and KSLFREE may not non-locally exit (return,<br />
* break, continue). However, it may signal an error.&nbsp; Between the KSLBEGIN and<br />
* the KSLEND you may not get or free another latch. (however, see KSLUPGRD).<br />
*<br />
* WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!<br />
* If you need to use an ONERROR block in the protected code, don't use the<br />
* fast latching macros!&nbsp; Just use the regular kslget/kslfre mechanism.<br />
*<br />
* Example usage:<br />
*<br />
*&nbsp;  void foo()<br />
*&nbsp;  {<br />
*&nbsp; &nbsp;  KSLBEGIN(foolatch)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /0 get the latch 0/<br />
*&nbsp; &nbsp; &nbsp;  protected_code;<br />
*&nbsp; &nbsp; &nbsp;  more_protected_code;<br />
*&nbsp; &nbsp;  KSLEND&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /0 free the latch 0/<br />
*&nbsp;  }<br />
*/<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 07 ***!!!<br />
<br />
#define KSLBEGIN(atmlatch)\<br />
if (1)\<br />
{\<br />
&nbsp; reg ksllt *atmlat = (atmlatch);\<br />
&nbsp; reg kslla *atmsta = ksuglk(ksugcp());\<br />
&nbsp; serc atmse;\<br />
&nbsp; if (bit(atmsta-&gt;ksllalow, ksllvl.ksllvbits[atmlat-&gt;kslltlvl]) \<br />
&nbsp; &nbsp; &nbsp; KSLDBG(|| atmsta-&gt;ksllalaq))\<br />
&nbsp; &nbsp; DISCARD kslget(atmlat, 1);\<br />
&nbsp; atmsta-&gt;ksllalaq = atmlat;\<br />
&nbsp; if (sclgtf(&amp;atmlat-&gt;kslltlat))\<br />
&nbsp; { \<br />
&nbsp; &nbsp; atmlat-&gt;kslltwgt++;\<br />
&nbsp; &nbsp; kslprrc(atmlat, TRUE);\<br />
&nbsp; } \<br />
&nbsp; else DISCARD kslges(atmlat, 1);<br />
<br />
#define KSLEND \<br />
&nbsp; if (!sclfr(&amp;atmse, &amp;atmlat-&gt;kslltlat)) kslferr(&amp;atmse);\<br />
&nbsp; kslprrc(atmlat, FALSE); \<br />
&nbsp; atmsta-&gt;ksllalaq = (ksllt *)0;\<br />
} else DISCARD(0);<br />
<br />
<br />
<br />
/* KSLUPGRD upgrades the state of a latch gotten using KSLBEGIN to be<br />
* the same as the state of a latch gotten using kslget.&nbsp; This allows the<br />
* latch to be freed using kslfre and it allows another latch to be gotten.<br />
* If a latch is upgraded it cannot be freed using KSLEND unless the latch is<br />
* first downgraded using KSLDNGRD.&nbsp; KSLUPGRD and KSLDNGRD can only be<br />
* invoked in the code that is textually between the KSLBEGIN and KSLEND.<br />
* N.B. KSLUPGRD cannot be used on latches gotten using KSLNBEGIN.<br />
*/<br />
<br />
#define KSLUPGRD \<br />
if (1)\<br />
{\<br />
&nbsp;  if (0 KSLDBG(|| atmsta-&gt;ksllalaq != atmlat))\<br />
&nbsp; &nbsp;  ksesic0(OERI(501));\<br />
&nbsp;  bis(atmsta-&gt;ksllalow, 1 &lt;&lt; atmlat-&gt;kslltlvl);\<br />
&nbsp;  atmsta-&gt;ksllalat[atmlat-&gt;kslltlvl] = atmlat;\<br />
&nbsp;  atmlat-&gt;kslltefd = kgetfd(ksmgpga);\<br />
&nbsp;  KSLDBG(atmsta-&gt;ksllalaq = (ksllt *)0;)\<br />
} else DISCARD(0)\<br />
<br />
#define KSLDNGRD \<br />
if (1)\<br />
{\<br />
&nbsp;  if (0 KSLDBG(|| atmsta-&gt;ksllalat[atmlat-&gt;kslltlvl] != atmlat))\<br />
&nbsp; &nbsp;  ksesic0(OERI(502));\<br />
&nbsp;  atmsta-&gt;ksllalaq = atmlat;\<br />
&nbsp;  bic(atmsta-&gt;ksllalow, 1 &lt;&lt; atmlat-&gt;kslltlvl);\<br />
&nbsp;  atmsta-&gt;ksllalat[atmlat-&gt;kslltlvl] = (ksllt *)0;\<br />
} else DISCARD(0)\<br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; _______________&nbsp;  CODE removed __________________<br />
<br />
/* PRIVATE TYPES AND CONSTANTS */<br />
<br />
<br />
/* Maximum&nbsp; latch level.&nbsp; Note that&nbsp;  the&nbsp; level immediately above this is<br />
* reserved for getting a duplicate latch (in nowait mode).<br />
*/<br />
#define&nbsp; KSLLMXLV 8&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* maximum value for kslldlev in kslld */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* NOTE: ksllalow and ksl.c need to change if KSLLMXLV &gt;= 14 */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* also the levelbits in kslget need to change as well */<br />
<br />
struct ksllvlt&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* level bits, used by get macros */<br />
{<br />
&nbsp; BITS16 ksllvbits[KSLLMXLV+2];<br />
};<br />
typedef struct ksllvlt ksllvlt;<br />
<br />
<br />
/* get latch slow, called by latch get macros */<br />
word kslges(/*_ struct ksllt *l, eword from_macro _*/);<br />
<br />
/* latch free error, called by latch get macros */<br />
void kslferr(/*_ serc *se _*/);<br />
<br />
<br />
/* Latch instance.&nbsp; The&nbsp; latch instance is&nbsp; the actual&nbsp; unit of locking&nbsp; (it<br />
* contains the OSD latch structure). <br />
*<br />
* There can be more than one latch with the same name (if they are allocated<br />
* dynamically).&nbsp; In this case there is one master latch allocated statically<br />
* called the parent latch and a number of dynamically allocated latches<br />
* called the child latches.&nbsp; The latches are chained together to<br />
* facilitate statistics gathering.<br />
*/<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 08 ***!!!<br />
<br />
struct ksllt<br />
{<br />
&nbsp;  sclt&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; kslltlat;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* OSD latch structure */<br />
<br />
&nbsp;  eword&nbsp; &nbsp; &nbsp; &nbsp;  kslltefd; /* error frame depth when gotten, this is used to */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* free the latch if an error is signalled while the latch is held */<br />
<br />
&nbsp;  ub4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  kslltngt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* count&nbsp; of times gotten nowait */<br />
&nbsp;  ub4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  kslltnfa;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* count of times failed nowait get */<br />
<br />
&nbsp;  ub4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  kslltwgt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* count of times gotten wait */<br />
&nbsp;  ub4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  kslltwff;&nbsp; &nbsp; &nbsp;  /* count of wait gets that failed first try */<br />
&nbsp;  ub4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  kslltwsl;&nbsp; /* count of times slept when failed to get latch */<br />
<br />
&nbsp;  struct ksllt *kslltchn;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* ptr to next child latch of this chain */<br />
&nbsp;  eword&nbsp; &nbsp; &nbsp; &nbsp;  kslltlvl;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* latch level, to enforce hierarchy */<br />
&nbsp;  b1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; kslltnum;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* latch number, to index descriptors */<br />
<br />
&nbsp;  struct kslla *kslltwkp;&nbsp;  /* process that is sleeping and should be woken */<br />
&nbsp;  /* this is a hint, the system will work though slower if this is not done */<br />
<br />
&nbsp;  ub4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  kslltwkc;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* count of wakeups that have been done */<br />
<br />
&nbsp;  ub4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  kslltwth;/* count of sleeps that were holding another latch */<br />
<br />
#define KSLHSTMAX 12&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* if you change this, must change x$ table */<br />
&nbsp;  ub4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  ksllthst[KSLHSTMAX];<br />
&nbsp;  /* Histogram of max exponential backoff per miss. The actual sleep time<br />
&nbsp; &nbsp; * corresponding to each bucket in the histogram is about<br />
&nbsp; &nbsp; * 2**((bucket+1)/2)-1 plus the sleep time of all the lower buckets.<br />
&nbsp; &nbsp; * All max exponential backoffs greater than the highest bucket are<br />
&nbsp; &nbsp; * added to the highest bucket.<br />
&nbsp; &nbsp; */<br />
&nbsp;  dvoid&nbsp; &nbsp; &nbsp; &nbsp; *kslltrec;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* recovery info for this latch */<br />
};<br />
typedef struct ksllt ksllt;<br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 09 ***!!!<br />
<br />
/* Latch descriptor.&nbsp; An array of these is allocated in the&nbsp; PGA.&nbsp; The array<br />
* contains&nbsp; a latch&nbsp; descriptor for&nbsp; every&nbsp; latch.&nbsp; The&nbsp; latch&nbsp;  descriptor<br />
* contains&nbsp; &nbsp; static information about that&nbsp; &nbsp; latch (such&nbsp; as&nbsp; the cleanup<br />
* procedure for the latch) that cannot be pointed at from the SGA&nbsp; (because<br />
* it is allocated in each process).&nbsp; It is found using the latch number.<br />
*/<br />
struct&nbsp;  kslld<br />
{<br />
&nbsp;  text&nbsp;  *kslldnam;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* human-readable latch name */<br />
&nbsp;  void&nbsp; (*kslldcln)(/*_ word action, ksllt *lp _*/);&nbsp; &nbsp; &nbsp; &nbsp; /* cleanup proc */<br />
&nbsp;  void&nbsp; (*kslldgcl)(/*_ kgsmp *gp, word action, struct kgslt *lp _*/);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* cleanup procedure for a generic component's latch */<br />
&nbsp;  size_t&nbsp; kslldrsz;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* recovery structure size */<br />
&nbsp;  b1&nbsp; &nbsp; &nbsp; kslldlvl;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* latch level */<br />
&nbsp;  b1&nbsp; &nbsp; &nbsp; kslldpnt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* TRUE if parent of a class of latches */<br />
&nbsp;  ub1&nbsp; &nbsp;  kslldlng;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* TRUE if latch can be held for long periods */<br />
};<br />
typedef&nbsp; struct&nbsp; kslld kslld;<br />
<br />
#define KSLLDMNAM 50&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* max size of the name field */<br />
<br />
typedef&nbsp; ksllt&nbsp; *kslltb[KSLMXLATCH];&nbsp; &nbsp; &nbsp; /* for pga latch table declaration */<br />
externref&nbsp; &nbsp; &nbsp; &nbsp; CONST_W_PTR kslld kslldt[];&nbsp;  /* table of latch descriptors */<br />
void&nbsp; &nbsp;  kslenl(/*_ void (*enumpr)(ksllt *l, ptr_t ctx), ptr_t ctx _*/);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* enumerate all */<br />
<br />
typedef bitvec ksllbv[BITVEC(KSLMXLATCH)];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* latch number bitvec */<br />
<br />
/* initialize recovery structures for latches */<br />
void kslirs(/*_ void _*/);<br />
<br />
void&nbsp; &nbsp;  ksldlt(/*_ word level _*/ );&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* latch trace */<br />
<br />
/* latch debugging: various bit values for the PGA variable ksldbg */<br />
#define KSLDBGTRC 0x1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* trace latching operations */<br />
#define KSLDBGPRT 0x2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* protect/unprotect recovery areas */<br />
<br />
/*******************/<br />
/* WAIT/POST/EVENT */<br />
/*******************/<br />
<br />
/* PUBLIC PROCEDURES */<br />
<br />
word&nbsp; &nbsp; kslaer(/*_ word nevent _*/);<br />
&nbsp; /*<br />
&nbsp; ** KSLAER: Allocate event range.&nbsp; Allocate (permanently)<br />
&nbsp; ** nevent events, return base.<br />
&nbsp; ** Callable during or after KSCNISGA,&nbsp; NOT latched.<br />
&nbsp; */<br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; _______________&nbsp;  CODE removed __________________<br />
<br />
/*********************/<br />
/* misc. definitions */<br />
/*********************/<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 10 ***!!!<br />
<br />
void kslnfy(/*_ word nfytype, ptr_t ctx _*/);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* notifier */<br />
<br />
/* fixed table callback routine */<br />
dvoid *ksltbl(/*_ CONST struct kqfco *cd, COLID ncols, ptr_t ctx, kghds *heap,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bitvec *whichcols, word msg, word (*rf)(ptr_t row) _*/);<br />
<br />
/* fixed table callback for latch name */<br />
size_t kslgnm(/*_ uword index, ptr_t space _*/);<br />
<br />
#endif&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* KSL */<br />
<br />
/* register notifier proc */<br />
KSCNTBDV(FADDR(kslnfy), (1&lt;&lt;KSCNISGA)|(1&lt;&lt;KSCNASGA))<br />
<br />
/* number of latches as SGA variable */<br />
#define kslltl KVIISDN(kslltl_)<br />
KVIISDV(kslltl_, "kslltl", "number of latches")<br />
<br />
/* latch table for display program */<br />
#define kslltt KSMSGADN(kslltb, kslltt_)<br />
KSMSGADV(kslltb, kslltt_)<br />
<br />
#define kslerb KVIISDN(kslerb_)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* event range base */<br />
KVIISDV(kslerb_, "kslerb", "event range base")<br />
<br />
#define kslnbe KVIISDN(kslnbe_)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* # of base events */<br />
KVIISDV(kslnbe_, "kslnbe", "# of base events")<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 11 ***!!!<br />
<br />
/* event statistics array: 1 for the system + 1 per session */<br />
#define kslesa KSMSGADN(ksles *, kslesa_)<br />
KSMSGADV(ksles *, kslesa_)<br />
<br />
/* level bits for macros to use */<br />
#define ksllvl KSMSGADN(ksllvlt, ksllvl_)<br />
KSMSGADV(ksllvlt, ksllvl_)<br />
<br />
/* number of CPUs in the system */<br />
#define kslcpu KVIISDN(kslcpu_)<br />
KVIISDV(kslcpu_, "kslcpu", "number of CPUs in the system")<br />
<br />
<br />
#ifndef SYS_SNGL<br />
#define kslrov KSMPGADN(kslrov_)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* pga rover for kslpse */<br />
KSMPGADV(struct ksupr *, kslrov_)<br />
#endif&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* SYS_SNGL */<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 12 ***!!!<br />
<br />
#define kslbwt KSMPGADN(kslbwt_)&nbsp; &nbsp;  /* beginning time of current wait event */<br />
KSMPGADV(ub4, kslbwt_)<br />
<br />
#define ksllsp KSMPGADN(ksllsp_)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* last wait resulted in post ? */<br />
KSMPGADV(word, ksllsp_)<br />
<br />
#define ksltri KSMPGADN(ksltri_)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* trace info for latches */<br />
KSMPGADV(struct ksltr *, ksltri_)<br />
<br />
#define ksldbg KSMPGADN(ksldbg_)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* latch debugging enabled ? */<br />
KSMPGADV(ub1, ksldbg_)<br />
<br />
#define kslcmt KSMPGADN(kslcmt_)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* tracing comment */<br />
KSMPGADV(CONST char *, kslcmt_)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 13 ***!!!<br />
<br />
/* latch activity event */<br />
#define ksllae KSLEVTDN(ksllae_)<br />
KSLEVTDV3(ksllae_, "latch activity", "address", "number", "process#")<br />
<br />
/* latch free event */<br />
#define ksllfe KSLEVTDN(ksllfe_)<br />
KSLEVTDV3(ksllfe_, "latch free", "address", "number", "tries")<br />
<br />
/* TRACES */<br />
KSDTRADV("LATCHES", FADDR(ksldlt))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* latch dump */<br />
<br />
KSDEVCBF(OER(10005), FADDR(kslcbf))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* latch op tracing */<br />
<br />
KSDEVCBF(OER(10072), FADDR(kslrpc))&nbsp; &nbsp; &nbsp; /* latch recovery memory protection */<br />
<br />
/* session initialization */<br />
KSMUGIFR(FADDR(kslies))<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 14 ***!!!<br />
<br />
/* fixed tables */<br />
/* latch objects */<br />
KQFTABC(ksllt, ksllt_c,&nbsp; "X$KSLLT", ksltbl, sizeof(ksllt ***), KQFOB081, 5)<br />
KQFCINT(ksllt, kslltnum,&nbsp; "KSLLTNUM")<br />
KQFCINT(ksllt, kslltlvl,&nbsp; "KSLLTLVL")<br />
KQFCFST(ksllt, "KSLLTNAM", KSLLDMNAM, kslgnm, kslgnm_n)<br />
KQFCINT(ksllt, kslltngt,&nbsp; "KSLLTNGT")<br />
KQFCINT(ksllt, kslltnfa,&nbsp; "KSLLTNFA")<br />
KQFCINT(ksllt, kslltwgt,&nbsp; "KSLLTWGT")<br />
KQFCINT(ksllt, kslltwff,&nbsp; "KSLLTWFF")<br />
KQFCINT(ksllt, kslltwkc,&nbsp; "KSLLTWKC")<br />
KQFCINT(ksllt, kslltwsl,&nbsp; "KSLLTWSL")<br />
KQFCINT(ksllt, kslltwth,&nbsp; "KSLLTWTH")<br />
KQFCINT(ksllt, ksllthst[0], "KSLLTHST0")<br />
KQFCINT(ksllt, ksllthst[1], "KSLLTHST1")<br />
KQFCINT(ksllt, ksllthst[2], "KSLLTHST2")<br />
KQFCINT(ksllt, ksllthst[3], "KSLLTHST3")<br />
KQFCINT(ksllt, ksllthst[4], "KSLLTHST4")<br />
KQFCINT(ksllt, ksllthst[5], "KSLLTHST5")<br />
KQFCINT(ksllt, ksllthst[6], "KSLLTHST6")<br />
KQFCINT(ksllt, ksllthst[7], "KSLLTHST7")<br />
KQFCINT(ksllt, ksllthst[8], "KSLLTHST8")<br />
KQFCINT(ksllt, ksllthst[9], "KSLLTHST9")<br />
KQFCINT(ksllt, ksllthst[10], "KSLLTHST10")<br />
KQFCINT(ksllt, ksllthst[11], "KSLLTHST11")<br />
KQFENDT(ksllt)<br />
<br />
/* latch descriptor */<br />
KQFTABL(kslld, kslld_c, "X$KSLLD", kslldt, kslltl, KQFOB082, 1)<br />
KQFCSTP(kslld, kslldnam, "KSLLDNAM")<br />
KQFENDT(kslld)<br />
<br />
/* event descriptors */<br />
KQFTABL(ksled, ksled_c, "X$KSLED", ksledt, kslnbe + 1, KQFOB182, 1)<br />
KQFCSTP(ksled, kslednam, "KSLEDNAM")<br />
KQFCSTP(ksled, ksledp1, "KSLEDP1")<br />
KQFCSTP(ksled, ksledp2, "KSLEDP2")<br />
KQFCSTP(ksled, ksledp3, "KSLEDP3")<br />
KQFENDT(ksled)<br />
<br />
/* event statistics for all sessions */<br />
KQFTABL(ksles, ksles_c, "X$KSLES", &amp;kslesa[kslnbe + 1],<br />
&nbsp; &nbsp; &nbsp; &nbsp; ((kslnbe + 1) * ksusga.ksusgsel), KQFOB183, 2)<br />
KQFCFIN(ksles, "KSLESSID", FADDR(kslgse), kslgse_n)<br />
KQFCFIN(ksles, "KSLESENM", FADDR(kslgne), kslgne_n)<br />
KQFCUIN(ksles, ksleswts, "KSLESWTS")<br />
KQFCUIN(ksles, kslestmo, "KSLESTMO")<br />
KQFCUIN(ksles, kslestim, "KSLESTIM")<br />
KQFENDT(ksles)<br />
<br />
/* instance-wide event statistics */<br />
KQFTABL(ksles, kslei_c, "X$KSLEI", kslesa, (kslnbe + 1), KQFOB190, 2)<br />
KQFCFIN(ksles, "KSLESWTS", FADDR(kslgwe), kslgwe_n)<br />
KQFCFIN(ksles, "KSLESTMO", FADDR(kslgto), kslgto_n)<br />
KQFCFIN(ksles, "KSLESTIM", FADDR(kslgte), kslgte_n)<br />
KQFENDT(ksles)<br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; !!!*** H 15 ****!!!<br />
<br />
/* spin count when fail to get latch */<br />
#define kslspc KSPPARDN(kslspc_)<br />
KSPPARDV("_latch_spin_count", kslspc_, kslspc_s, kslspc_l, kslspc_p,<br />
&nbsp; &nbsp; &nbsp; &nbsp;  LCCMDINT, 0, NULLP(text), 100, KSPLS1(NULLP(text)),<br />
&nbsp; &nbsp; &nbsp; &nbsp;  KSPLS2(1, EWORDMAXVAL), 0, KSPLS1(NULLP(word)),<br />
&nbsp; &nbsp; &nbsp; &nbsp;  "amount to spin waiting for a latch")<br />
<br />
/* holds value of kslspc */<br />
#define kslspi KSMSGADN(eword, kslspi_)<br />
KSMSGADV(eword, kslspi_)<br />
<br />
<br />
/* max amount to sleep when waiting for a latch and holding another */<br />
#define kslmxs KSPPARDN(kslmxs_)<br />
KSPPARDV("_max_sleep_holding_latch", kslmxs_, kslmxs_s, kslmxs_l, kslmxs_p,<br />
&nbsp; &nbsp; &nbsp; &nbsp;  LCCMDINT, 0, NULLP(text), 4, KSPLS1(NULLP(text)),<br />
&nbsp; &nbsp; &nbsp; &nbsp;  KSPLS2(0, EWORDMAXVAL), 0, KSPLS1(NULLP(word)),<br />
&nbsp; &nbsp; &nbsp; &nbsp;  "max time to sleep while holding a latch")<br />
<br />
/* holds value of kslmxs */<br />
#define kslmsl KSMSGADN(eword, kslmsl_)<br />
KSMSGADV(eword, kslmsl_)<br />
<br />
<br />
/* maximum sleep during any exponential backoff in hundreths of seconds */<br />
#define kslmes KSPPARDN(kslmes_)<br />
KSPPARDV("_max_exponential_sleep", kslmes_, kslmes_s, kslmes_l, kslmes_p,<br />
&nbsp; &nbsp; &nbsp; &nbsp;  LCCMDINT, 0, NULLP(text), 0, KSPLS1(NULLP(text)),<br />
&nbsp; &nbsp; &nbsp; &nbsp;  KSPLS2(0, EWORDMAXVAL), 0, KSPLS1(NULLP(word)),<br />
&nbsp; &nbsp; &nbsp; &nbsp;  "max sleep during exponential backoff")<br />
<br />
/* holds value of kslmes */<br />
#define kslmex KSMSGADN(eword, kslmex_)<br />
KSMSGADV(eword, kslmex_)<br />
<br />
<br />
/* if this is 1 then we use the post waiters protocol for latches that<br />
* are declared KSLLALNG, if it is greater than one we use it for all<br />
* latches.<br />
*/<br />
#define kslpsw KSPPARDN(kslpsw_)<br />
KSPPARDV("_latch_wait_posting", kslpsw_, kslpsw_s, kslpsw_l, kslpsw_p,<br />
&nbsp; &nbsp; &nbsp; &nbsp;  LCCMDINT, 0, NULLP(text), 1, KSPLS1(NULLP(text)),<br />
&nbsp; &nbsp; &nbsp; &nbsp;  KSPLS2(0, EWORDMAXVAL), 0, KSPLS1(NULLP(word)),<br />
&nbsp; &nbsp; &nbsp; &nbsp;  "post sleeping processes when free latch")<br />
<br />
/* holds value of kslpsw */<br />
#define kslpwt KSMSGADN(eword, kslpwt_)<br />
KSMSGADV(eword, kslpwt_)<br />
<br />
/* latch recovery alignment parameter:<br />
* specifies a list of latch numbers for which recovery alignment is enabled.<br />
* valid numbers are [0...max_latches); if any number in the list is outside<br />
* the range, then it is ignored (note that the default value is KSLMXLATCH<br />
* - not 0 -, which causes no alignment to be enabled).&nbsp; If any number in the<br />
* list is "999", then recovery alignment is enabled for ALL latches which are<br />
* defined through one of the new compile-time service macros KSLLTDV2 or<br />
* KGSLLDV2.&nbsp; Use the "LATCH#" column in V$LATCH to get latch numbers.<br />
*/<br />
#define kslrpp KSPPARDN(kslrpp_)<br />
KSPPARDV("_latch_recovery_alignment", kslrpp_, kslrpp_s, kslrpp_l, kslrpp_p,<br />
&nbsp; &nbsp; &nbsp; &nbsp;  LCCMDINT, 0, NULLP(text), KSLMXLATCH, KSPLS1(NULLP(text)),<br />
&nbsp; &nbsp; &nbsp; &nbsp;  KSPLS2(0, EWORDMAXVAL), 0, KSPLS1(NULLP(word)),<br />
&nbsp; &nbsp; &nbsp; &nbsp;  "align latch recovery structures")<br />
<br />
/* holds value of kslrpp converted to a bitvec */<br />
#define kslrpv KSMSGADN(ksllbv, kslrpv_)<br />
KSMSGADV(ksllbv, kslrpv_)<br />
<br />
/* latch that synchronizes latch wait list */<br />
#define kslwlst KSLLATDN(kslwlst_)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
KSLLATDV(kslwlst_, "latch wait list", FADDR(ksllcu), KSLLMXLV+1)<br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Extract from ksl.c<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ==================<br />
<br />
/*<br />
** Get the latch specified by "id", on behalf&nbsp; of&nbsp; the&nbsp; current<br />
** session.&nbsp; If "wait" is&nbsp; FALSE,&nbsp; return&nbsp; immediately&nbsp; if&nbsp; the<br />
** latch is in use; if TRUE, keep trying and&nbsp; return&nbsp; when&nbsp; the<br />
** latch has been granted.&nbsp; Return TRUE&nbsp; if&nbsp; and&nbsp; only&nbsp; if&nbsp; the<br />
** latch was granted.&nbsp; Raise an error if this is cleanup,&nbsp; wait<br />
** is TRUE, and the latch is busy.&nbsp; This procedure&nbsp; checks&nbsp; for<br />
** errors in latch sequence (based on level), and records&nbsp; what<br />
** latches are held so they can be freed if needed.<br />
*/<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 01 ***!!!<br />
<br />
word&nbsp; &nbsp; &nbsp; &nbsp;  kslget(l, wait)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* get a latch */<br />
reg0 ksllt&nbsp; *l;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* latch we are latching */<br />
&nbsp; &nbsp;  word&nbsp; &nbsp; wait;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* wait for latch or just return */<br />
{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 02 ***!!!<br />
<br />
&nbsp; reg1 kslla&nbsp;  *state;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* latch state */<br />
&nbsp; reg2 word&nbsp; &nbsp;  level;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* latching level */<br />
<br />
&nbsp; /* initialize */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 03 ***!!!<br />
<br />
&nbsp; state = ksuglk(ksugcp());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* get process latching state */<br />
&nbsp; level = l-&gt;kslltlvl;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* get level of latch */<br />
<br />
#ifdef KSLDEBUG<br />
&nbsp; /* if currently hold a fast latch, cannot get another latch */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 04 ***!!!<br />
<br />
&nbsp; if (state-&gt;ksllalaq)<br />
&nbsp; &nbsp; ksesic2(OERI(503), ksenrg(state-&gt;ksllalaq),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ksesrgl((text *)kslldt[state-&gt;ksllalaq-&gt;kslltnum].kslldnam));<br />
#endif<br />
<br />
&nbsp; /* Enforce latch hirearchy to prevent deadlocks.<br />
&nbsp;  * Check if a latch is already held at this level or any higher level.<br />
&nbsp;  */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 05 ***!!!<br />
<br />
&nbsp; if (bit(state-&gt;ksllalow, levelbits[level]))<br />
&nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 06 ***!!!<br />
<br />
&nbsp; &nbsp; if (!wait)<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 07 ***!!!<br />
<br />
&nbsp; &nbsp; &nbsp; if (!state-&gt;ksllalat[level])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* no latch gotten at this level */<br />
&nbsp; &nbsp; &nbsp; &nbsp; ;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* allow nowait get to proceded */<br />
&nbsp; &nbsp; &nbsp; /* allow one duplicate get at a level if it is gotten nowait */<br />
&nbsp; &nbsp; &nbsp; else if (state-&gt;ksllalat[level] != l &amp;&amp; !state-&gt;ksllalat[KSLLMXLV+1])<br />
&nbsp; &nbsp; &nbsp; &nbsp; level = KSLLMXLV+1;&nbsp; &nbsp;  /* use the slot that is one past the highest */<br />
&nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* never signal conflict on nowait get */<br />
&nbsp; &nbsp; &nbsp; &nbsp; return FALSE;<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; else<br />
&nbsp; &nbsp; &nbsp; ksesic4(<br />
&nbsp; &nbsp; &nbsp; &nbsp; OERI(504),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* kslget: failure to follow lock hierarchy */<br />
&nbsp; &nbsp; &nbsp; &nbsp; ksenrg(l), ksenrg(state-&gt;ksllalow),<br />
&nbsp; &nbsp; &nbsp; &nbsp; ksenrg(level), ksesrgl((text *)kslldt[l-&gt;kslltnum].kslldnam));<br />
&nbsp; }<br />
<br />
&nbsp; /* set "we are waiting for the latch" and go try to get it */<br />
&nbsp; state-&gt;ksllalaq = l;<br />
<br />
&nbsp; /* Do a fast try to get the latch */<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 08 ***!!!<br />
<br />
&nbsp; if (sclgtf(&amp;l-&gt;kslltlat))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* do the test and set (or equivalent) */<br />
&nbsp; {<br />
&nbsp; &nbsp; /* Got the latch on first try */<br />
&nbsp; &nbsp; bis(state-&gt;ksllalow, 1 &lt;&lt; level);&nbsp; &nbsp; /* set level bit for level checking */<br />
&nbsp; &nbsp; state-&gt;ksllalat[level] = l;&nbsp; &nbsp; &nbsp;  /* indicate latch gotten at this level */<br />
&nbsp; &nbsp; l-&gt;kslltefd = kgetfd(ksmgpga);&nbsp;  /* error frame depth for error recovery */<br />
<br />
&nbsp; &nbsp; /* Note that the number of latch gets is used during cleanup (it is not<br />
&nbsp; &nbsp;  *&nbsp; just for statistics).&nbsp; So don't delete this code.<br />
&nbsp; &nbsp;  */<br />
&nbsp; &nbsp; if (wait)<br />
&nbsp; &nbsp; &nbsp; l-&gt;kslltwgt++;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* bump wait gets */<br />
&nbsp; &nbsp; else<br />
&nbsp; &nbsp; &nbsp; l-&gt;kslltngt++;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* bump nowait gets */<br />
<br />
&nbsp; &nbsp; KSLDBG(state-&gt;ksllalaq = (ksllt *)0;)<br />
<br />
&nbsp; &nbsp; /* check if latch debugging is turned on */<br />
&nbsp; &nbsp; if (ksldbg)<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; /* set trace info if appropriate */<br />
&nbsp; &nbsp; &nbsp; kslsgtr(l, kslcmt);<br />
<br />
&nbsp; &nbsp; &nbsp; /* unprotect the latch's recovery structure if necessary */<br />
&nbsp; &nbsp; &nbsp; kslprrc(l, TRUE);<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; return TRUE;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* return success */<br />
&nbsp; }<br />
&nbsp; else if (!wait)&nbsp; &nbsp;  /* if failed to get the latch and not supposed to wait */<br />
&nbsp; {<br />
&nbsp; &nbsp; /* Bump nowait attempts. This increment is not protected by the latch,<br />
&nbsp; &nbsp;  * so it may be lost or garbled if several processes do this at the same<br />
&nbsp; &nbsp;  * time.<br />
&nbsp; &nbsp;  */<br />
&nbsp; &nbsp; l-&gt;kslltnfa++;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* nowait failures */<br />
&nbsp; &nbsp; state-&gt;ksllalaq = (ksllt *)0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* not trying to get it anymore */<br />
&nbsp; &nbsp; return FALSE;<br />
&nbsp; }<br />
<br />
&nbsp; /* Someone else has the latch, we must wait for it.&nbsp; Call kslges indirectly<br />
&nbsp;  * so the compiler will not inline the routine (this causes many registers<br />
&nbsp;  * to be saved unnecessarily).<br />
&nbsp;  */&nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 09 ***!!!<br />
<br />
&nbsp; return (*kslger)(l, FALSE);<br />
}<br />
<br />
<br />
/* remove myself from list of waiter processes on a latch. */<br />
STATICF void kslwrmv(state)<br />
reg0 kslla *state;<br />
{<br />
&nbsp; reg1 kslla&nbsp; *wait_proc;<br />
&nbsp; reg2 kslla **proc_link;<br />
<br />
&nbsp; /* walk list of processes waiting for this latch */<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 10 ***!!!<br />
<br />
&nbsp; for (wait_proc = state-&gt;ksllawtr-&gt;kslltwkp,<br />
&nbsp; &nbsp; &nbsp;  proc_link = &amp;state-&gt;ksllawtr-&gt;kslltwkp;<br />
&nbsp; &nbsp; &nbsp;  wait_proc;<br />
&nbsp; &nbsp; &nbsp;  proc_link = &amp;wait_proc-&gt;ksllanxw, wait_proc = *proc_link)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 11 ***!!!<br />
<br />
&nbsp; &nbsp; if (wait_proc == state)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* if waiter is me */<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; *proc_link = state-&gt;ksllanxw;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* pop myself from list */<br />
&nbsp; &nbsp; &nbsp; break;<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; /* Note that if I was previously killed while linking or unlinking myself<br />
&nbsp;  * from a wait list, I might never have made it on the list, but I would<br />
&nbsp;  * still have my state set as if I did.&nbsp; We always link on the the waiter<br />
&nbsp;  * list last when adding to the wait list, and unlink first when removing<br />
&nbsp;  * from the wait list.&nbsp; Therefore I need to clear my state whether I am on<br />
&nbsp;  * the list or not to cleanup from process death.<br />
&nbsp;  */<br />
&nbsp; state-&gt;ksllanxw = (kslla *)0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* no next waiter */<br />
&nbsp; state-&gt;ksllawtr = (ksllt *)0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* not on wait list for this latch */<br />
}<br />
<br />
<br />
/* Second part of kslget.&nbsp;  We failed to get&nbsp; the latch on the&nbsp; first try so<br />
* now we have to wait for it.<br />
*/<br />
word&nbsp; kslges(l, from_macro)<br />
reg0 ksllt&nbsp;  *l;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* latch we are latching */<br />
eword from_macro;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* true if called from kslatm macro */<br />
{<br />
&nbsp; ub4&nbsp; &nbsp; i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* miss counter */<br />
<br />
&nbsp; reg1 kslla&nbsp;  *state;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* latch state */<br />
&nbsp; reg2 word&nbsp; &nbsp;  level;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* latching level */<br />
&nbsp; reg3 eword&nbsp; &nbsp; max_backoff = kslmex;&nbsp; &nbsp; &nbsp; &nbsp; /* Let's initialize this, okay? */<br />
&nbsp; &nbsp; &nbsp;  eword&nbsp; &nbsp; other_latch = FALSE;<br />
<br />
&nbsp; /* initialize */<br />
&nbsp; state = ksuglk(ksugcp());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* get process latching state */<br />
&nbsp; level = l-&gt;kslltlvl;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* get level of latch */<br />
<br />
&nbsp; /* Don't sleep too long if currently holding a latch since this will tend to<br />
&nbsp;  * backup the people waiting for me.&nbsp; This does not apply if the latch is<br />
&nbsp;  * an allocated child latch since there are lots of those.<br />
&nbsp;  */<br />
&nbsp; if (state-&gt;ksllalow)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* if currently holding a latch */<br />
&nbsp; {<br />
&nbsp; &nbsp; for (i = 0; i &lt;= level; i++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* for all latches I am holding */<br />
&nbsp; &nbsp; &nbsp; if (state-&gt;ksllalat[i] &amp;&amp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !state-&gt;ksllalat[i]-&gt;kslltchn)&nbsp; &nbsp; &nbsp;  /* if holding non-child latch */<br />
&nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; max_backoff = kslmsl;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* set max backoff to smaller value */<br />
&nbsp; &nbsp; &nbsp; &nbsp; other_latch = TRUE;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* remember we're holding another latch */<br />
&nbsp; &nbsp; &nbsp; &nbsp; break;<br />
&nbsp; &nbsp; &nbsp; }<br />
&nbsp; }<br />
<br />
&nbsp; /* keep trying to get the latch until we succeed */<br />
&nbsp; for (i = 0; ; i++)<br />
&nbsp; {<br />
&nbsp; &nbsp; serc&nbsp;  se;<br />
<br />
&nbsp; &nbsp; /* set "we are waiting for the latch" and go get it */<br />
&nbsp; &nbsp; state-&gt;ksllalaq = l;<br />
<br />
&nbsp; &nbsp; /* try to get the latch again */<br />
&nbsp; &nbsp; if (sclgts(&amp;se, &amp;l-&gt;kslltlat,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* the latch to get */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  ksugpi(ksugcp()),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* the OSD process structure */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  &amp;state-&gt;ksllalaq,&nbsp; &nbsp; &nbsp;  /* pointer to latch trying to acquire */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  ksuicl()))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* am I the cleanup process */<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; l-&gt;kslltwgt++;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* bump wait gets statistic */<br />
&nbsp; &nbsp; &nbsp; l-&gt;kslltwff++;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* bump failed first attempt statistic */<br />
&nbsp; &nbsp; &nbsp; l-&gt;kslltwsl += i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* increment sleeps statistic */<br />
&nbsp; &nbsp; &nbsp; if (state-&gt;ksllalow) l-&gt;kslltwth++;&nbsp; /* increment sleeps holding latch */<br />
<br />
&nbsp; &nbsp; &nbsp; /* increment histogram of wait times */<br />
&nbsp; &nbsp; &nbsp; if (i &gt;= KSLHSTMAX)<br />
&nbsp; &nbsp; &nbsp; &nbsp; l-&gt;ksllthst[KSLHSTMAX-1]++;<br />
&nbsp; &nbsp; &nbsp; else l-&gt;ksllthst[i]++;&nbsp; &nbsp;  <br />
<br />
&nbsp; &nbsp; &nbsp; if (!from_macro)&nbsp; &nbsp; &nbsp;  /* don't set these if called by fast path macro */<br />
&nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; bis(state-&gt;ksllalow, 1 &lt;&lt; level);/* set level bit for level checking */<br />
&nbsp; &nbsp; &nbsp; &nbsp; state-&gt;ksllalat[level] = l;&nbsp;  /* indicate latch gotten at this level */<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; KSLDBG(state-&gt;ksllalaq = (ksllt *)0;)<br />
&nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; l-&gt;kslltefd = kgetfd(ksmgpga); /* error frame depth for error recovery */<br />
<br />
&nbsp; &nbsp; &nbsp; /* check if latch debugging is turned on */<br />
&nbsp; &nbsp; &nbsp; if (ksldbg)<br />
&nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; /* set trace info if appropriate */<br />
&nbsp; &nbsp; &nbsp; &nbsp; kslsgtr(l, kslcmt);<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; /* unprotect the latch's recovery structure if necessary */<br />
&nbsp; &nbsp; &nbsp; &nbsp; kslprrc(l, TRUE);<br />
&nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; return TRUE;<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; else<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; /* We did not get the latch, someone else must have it.&nbsp; We must wait */<br />
&nbsp; &nbsp; &nbsp; state-&gt;ksllalaq = (ksllt *)0;&nbsp; &nbsp; &nbsp;  /* we are not trying to get it now */<br />
<br />
&nbsp; &nbsp; &nbsp; if (SERC_ERROR(se))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* if something went wrong, signal error */<br />
&nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; (*ksloet)();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* Dump useful info */<br />
&nbsp; &nbsp; &nbsp; &nbsp; DISCARD ksecrs(&amp;se);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* record error code */<br />
&nbsp; &nbsp; &nbsp; &nbsp; ksesic0(OERI(506));<br />
&nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; if (i == 5 &amp;&amp; !ksuicl()) /* if waited for a few hundreth's of a second */<br />
&nbsp; &nbsp; &nbsp; &nbsp; ksupsx();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* post cleanup in case dead process holds latch */<br />
<br />
&nbsp; &nbsp; &nbsp; /* if should use post waiters option to latching */<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 12 ***!!!<br />
<br />
&nbsp; &nbsp; &nbsp; if (&nbsp;  kslpwt&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* waiting is enabled */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;&amp; l != kslwlst&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* not waiting for the waiter list latch */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;&amp; !from_macro&nbsp; &nbsp; &nbsp; &nbsp;  /* not from macro, macros don't call kslfre */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;&amp; (i == 0 ||&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* first time through loop */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !state-&gt;ksllawtr)&nbsp; &nbsp; /* someone woke me but I didn't get latch */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;&amp; !state-&gt;ksllalat[kslwlst-&gt;kslltlvl]&nbsp; &nbsp; /* no out of order latch */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;&amp; (kslpwt &gt; 1 ||&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* waiting enabled for all latches */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; kslldt[l-&gt;kslltnum].kslldlng))&nbsp; &nbsp; &nbsp;  /* this is a 'long' latch */<br />
&nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; /* Add myself to the head of the waiter list. */<br />
&nbsp; &nbsp; &nbsp; &nbsp; KSLBEGIN(kslwlst)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* get latch waiter list latch */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* If I am still on waiter list of a latch that I am holding I need<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  * to get off that list before going on another waiter list.&nbsp; Note<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  * that I don't normally take myself off a waiter list until I free<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  * the latch to avoid adding extra code path under the latch that<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  * people are waiting for.&nbsp; This is why I could be on a waiter list<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  * while I am holding the latch.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (state-&gt;ksllawtr)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* if on waiter list for a latch */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; kslwrmv(state);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* take myself off the list */<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state-&gt;ksllawtr = l;&nbsp; &nbsp; &nbsp; /* latch whose waiter list I am going on */<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* give preference to waiters that are holding another latch */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (l-&gt;kslltwkp&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* if someone already on wait list */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;&amp; !other_latch)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* and I am not holding a latch */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* put myself in second slot of wait list in case the person in<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  * the first slot is holding a latch.&nbsp; This gives him precedence.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  */<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* people after first guy are now after me */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state-&gt;ksllanxw = l-&gt;kslltwkp-&gt;ksllanxw;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; l-&gt;kslltwkp-&gt;ksllanxw = state;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* I am after first guy */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* put myself at the head of the waiter list */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state-&gt;ksllanxw = l-&gt;kslltwkp;&nbsp; &nbsp;  /* head of list goes after me */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; l-&gt;kslltwkp = state;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* I go at head of list */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; KSLEND&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* remember I am on the list */<br />
&nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; state-&gt;ksllawat = l;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* set latch we are waiting for */<br />
<br />
&nbsp; &nbsp; &nbsp; /* do exponential backoff */<br />
&nbsp; &nbsp; &nbsp; kslewt3(i, max_backoff, (state-&gt;ksllawtr ? TRUE : FALSE),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ksllfe, l, l-&gt;kslltnum, i);<br />
<br />
&nbsp; &nbsp; &nbsp; state-&gt;ksllawat = (ksllt *)0;&nbsp; &nbsp; &nbsp; &nbsp; /* clear latch we are waiting for */<br />
<br />
&nbsp; &nbsp; &nbsp; ksucfi();&nbsp; /* Check for any interrupts which are fatal to the instance */<br />
<br />
&nbsp; &nbsp; &nbsp; ksecss(&amp;se);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* check for error */<br />
<br />
&nbsp; &nbsp; &nbsp; if (i &gt; 7 &amp;&amp; ksuicl())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* if PMON and waited long enough */<br />
&nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; /* PMON has not been able to get the latch.&nbsp; The latch might be held<br />
&nbsp; &nbsp; &nbsp; &nbsp;  * by a dead process so search for dead processes, and free their<br />
&nbsp; &nbsp; &nbsp; &nbsp;  * latches.&nbsp; When freeing dead processes latches, PMON must only free<br />
&nbsp; &nbsp; &nbsp; &nbsp;  * latches that have a higher level than the highest level latch he<br />
&nbsp; &nbsp; &nbsp; &nbsp;  * is currently holding since freeing a latch can cause another<br />
&nbsp; &nbsp; &nbsp; &nbsp;  * latch to be gotten which could lead to a conflict with the latches<br />
&nbsp; &nbsp; &nbsp; &nbsp;  * PMON already holds.<br />
&nbsp; &nbsp; &nbsp; &nbsp;  */<br />
&nbsp; &nbsp; &nbsp; &nbsp; DISCARD ksuxfl();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* free dead process' latches */<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !!!*** C 13 ***!!!<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; if (i == 200)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* if waited for a long time */<br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ksupr *pr = kslown(l);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* process that holds the latch */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ksdwrf("PMON unable to acquire latch %lx %s\n", (unsigned long)l,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  (char *)kslldt[l-&gt;kslltnum].kslldnam);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (pr)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ksdwrf("&nbsp; possible holder pid = %d ospid=%.*s\n", (int)ksuprp(pr),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  (int)ksugpri(pr)-&gt;ksuospdl, (char *)ksugpri(pr)-&gt;ksuospid);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ksdddt();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* write time stamp */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ksdfls();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  /* flush dump file */<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ksdwra("PMON failed to acquire latch, see PMON dump");<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; }<br />
&nbsp; }<br />
}<br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oratypes.h<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ==========<br />
<br />
/* /v71/d2/713/oracore/public/sx.h */<br />
<br />
<br />
/*<br />
ORACLE, Copyright (c) 1982, 1983, 1986, 1990 ORACLE Corporation<br />
ORACLE Utilities, Copyright (c) 1981, 1982, 1983, 1986, 1990, 1991 ORACLE Corp<br />
<br />
Restricted Rights<br />
This program is an unpublished work under the Copyright Act of the<br />
United States and is subject to the terms and conditions stated in<br />
your&nbsp; license&nbsp; agreement&nbsp; with&nbsp; ORACORP&nbsp; including&nbsp; retrictions on<br />
use, duplication, and disclosure.<br />
<br />
Certain uncopyrighted ideas and concepts are also contained herein.<br />
These are trade secrets of ORACORP and cannot be&nbsp; used&nbsp; except&nbsp; in<br />
accordance with the written permission of ORACLE Corporation.<br />
*/<br />
<br />
<br />
/* $Header: sx.h 7.18 94/04/05 18:34:34 tswang Osd&lt;unix&gt; $ */<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
#ifndef ORASTDDEF<br />
# include &lt;stddef.h&gt;<br />
# define ORASTDDEF<br />
#endif<br />
<br />
#ifndef ORALIMITS<br />
# include &lt;limits.h&gt;<br />
# define ORALIMITS<br />
#endif<br />
<br />
#ifndef&nbsp; SX_ORACLE<br />
#define&nbsp; SX_ORACLE<br />
#define&nbsp; SX<br />
#define&nbsp; ORATYPES<br />
<br />
<br />
#ifndef TRUE<br />
# define TRUE&nbsp; 1<br />
# define FALSE 0<br />
#endif<br />
<br />
<br />
<br />
#ifdef lint<br />
# ifndef mips<br />
#&nbsp; define signed<br />
# endif<br />
#endif<br />
<br />
#ifdef ENCORE_88K<br />
# ifndef signed<br />
#&nbsp; define signed<br />
# endif<br />
#endif<br />
<br />
#ifdef SYSV_386<br />
# ifndef signed<br />
#&nbsp; define signed<br />
# endif<br />
#endif<br />
<br />
<br />
<br />
<br />
<br />
#ifndef lint<br />
typedef&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int eword;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />
typedef unsigned int uword;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />
typedef&nbsp;  signed int sword;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />
#else<br />
#define eword int<br />
#define uword unsigned int<br />
#define sword signed int<br />
#endif<br />
<br />
#define&nbsp; EWORDMAXVAL&nbsp; ((eword) INT_MAX)<br />
#define&nbsp; EWORDMINVAL&nbsp; ((eword)&nbsp; &nbsp; &nbsp;  0)<br />
#define&nbsp; UWORDMAXVAL&nbsp; ((uword)UINT_MAX)<br />
#define&nbsp; UWORDMINVAL&nbsp; ((uword)&nbsp; &nbsp; &nbsp;  0)<br />
#define&nbsp; SWORDMAXVAL&nbsp; ((sword) INT_MAX)<br />
#define&nbsp; SWORDMINVAL&nbsp; ((sword) INT_MIN)<br />
#define&nbsp; MINEWORDMAXVAL&nbsp; ((eword)&nbsp; 32767)<br />
#define&nbsp; MAXEWORDMINVAL&nbsp; ((eword)&nbsp; &nbsp; &nbsp; 0)<br />
#define&nbsp; MINUWORDMAXVAL&nbsp; ((uword)&nbsp; 65535)<br />
#define&nbsp; MAXUWORDMINVAL&nbsp; ((uword)&nbsp; &nbsp; &nbsp; 0)<br />
#define&nbsp; MINSWORDMAXVAL&nbsp; ((sword)&nbsp; 32767)<br />
#define&nbsp; MAXSWORDMINVAL&nbsp; ((sword) -32767)<br />
<br />
<br />
#ifndef lint<br />
# ifdef mips<br />
typedef&nbsp;  signed char&nbsp; eb1;<br />
# else<br />
typedef&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; char&nbsp; eb1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />
# endif<br />
typedef unsigned char&nbsp; ub1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />
typedef&nbsp;  signed char&nbsp; sb1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />
#else<br />
#define eb1 char<br />
#define ub1 unsigned char<br />
#define sb1 signed char<br />
#endif<br />
<br />
#define EB1MAXVAL ((eb1)SCHAR_MAX)<br />
#define EB1MINVAL ((eb1)&nbsp; &nbsp; &nbsp; &nbsp; 0)<br />
#if defined(mips)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
# ifndef lint<br />
#&nbsp; define UB1MAXVAL (UCHAR_MAX)<br />
# endif<br />
#endif<br />
#ifndef UB1MAXVAL<br />
# ifdef SCO_UNIX<br />
# define UB1MAXVAL (UCHAR_MAX)<br />
# else<br />
# define UB1MAXVAL ((ub1)UCHAR_MAX)<br />
# endif<br />
#endif<br />
#define UB1MINVAL ((ub1)&nbsp; &nbsp; &nbsp; &nbsp; 0)<br />
#define SB1MAXVAL ((sb1)SCHAR_MAX)<br />
#define SB1MINVAL ((sb1)SCHAR_MIN)<br />
#define MINEB1MAXVAL ((eb1)&nbsp; 127)<br />
#define MAXEB1MINVAL ((eb1)&nbsp; &nbsp; 0)<br />
#define MINUB1MAXVAL ((ub1)&nbsp; 255)<br />
#define MAXUB1MINVAL ((ub1)&nbsp; &nbsp; 0)<br />
#define MINSB1MAXVAL ((sb1)&nbsp; 127)<br />
#define MAXSB1MINVAL ((sb1) -127)<br />
<br />
#define UB1BITS&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CHAR_BIT<br />
#define UB1MASK&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0xff<br />
<br />
<br />
typedef&nbsp; unsigned char text;<br />
<br />
<br />
#ifndef lint<br />
typedef&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; short&nbsp; &nbsp; eb2;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
typedef unsigned short&nbsp; &nbsp; ub2;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
typedef&nbsp;  signed short&nbsp; &nbsp; sb2;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
#else<br />
#define eb2&nbsp; short<br />
#define ub2&nbsp; unsigned short<br />
#define sb2&nbsp; signed short<br />
#endif<br />
<br />
#define EB2MAXVAL ((eb2) SHRT_MAX)<br />
#define EB2MINVAL ((eb2)&nbsp; &nbsp; &nbsp; &nbsp; 0)<br />
#define UB2MAXVAL ((ub2)USHRT_MAX)<br />
#define UB2MINVAL ((ub2)&nbsp; &nbsp; &nbsp; &nbsp; 0)<br />
#define SB2MAXVAL ((sb2) SHRT_MAX)<br />
#define SB2MINVAL ((sb2) SHRT_MIN)<br />
#define MINEB2MAXVAL ((eb2) 32767)<br />
#define MAXEB2MINVAL ((eb2)&nbsp; &nbsp;  0)<br />
#define MINUB2MAXVAL ((ub2) 65535)<br />
#define MAXUB2MINVAL ((ub2)&nbsp; &nbsp;  0)<br />
#define MINSB2MAXVAL ((sb2) 32767)<br />
#define MAXSB2MINVAL ((sb2)-32767)<br />
<br />
<br />
#ifndef lint<br />
typedef&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long&nbsp; eb4;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />
typedef unsigned long&nbsp; ub4;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />
typedef&nbsp;  signed long&nbsp; sb4;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />
#else<br />
#define eb4 long<br />
#define ub4 unsigned long<br />
#define sb4 signed long<br />
#endif<br />
<br />
#define EB4MAXVAL ((eb4) LONG_MAX)<br />
#define EB4MINVAL ((eb4)&nbsp; &nbsp; &nbsp; &nbsp; 0)<br />
#define UB4MAXVAL ((ub4)ULONG_MAX)<br />
#define UB4MINVAL ((ub4)&nbsp; &nbsp; &nbsp; &nbsp; 0)<br />
#define SB4MAXVAL ((sb4) LONG_MAX)<br />
#define SB4MINVAL ((sb4) LONG_MIN)<br />
#define MINEB4MAXVAL ((eb4) 2147483647)<br />
#define MAXEB4MINVAL ((eb4)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0)<br />
#define MINUB4MAXVAL ((ub4) 4294967295)<br />
#define MAXUB4MINVAL ((ub4)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0)<br />
#define MINSB4MAXVAL ((sb4) 2147483647)<br />
#define MAXSB4MINVAL ((sb4)-2147483647)<br />
<br />
<br />
#ifndef lint<br />
typedef unsigned long&nbsp; ubig_ora;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
typedef&nbsp;  signed long&nbsp; sbig_ora;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
#else<br />
#define ubig_ora unsigned long<br />
#define sbig_ora signed long<br />
#endif<br />
<br />
#define UBIG_ORAMAXVAL ((ubig_ora)ULONG_MAX)<br />
#define UBIG_ORAMINVAL ((ubig_ora)&nbsp; &nbsp; &nbsp; &nbsp; 0)<br />
#define SBIG_ORAMAXVAL ((sbig_ora) LONG_MAX)<br />
#define SBIG_ORAMINVAL ((sbig_ora) LONG_MIN)<br />
#define MINUBIG_ORAMAXVAL ((ubig_ora) 4294967295)<br />
#define MAXUBIG_ORAMINVAL ((ubig_ora)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0)<br />
#define MINSBIG_ORAMAXVAL ((sbig_ora) 2147483647)<br />
#define MAXSBIG_ORAMINVAL ((sbig_ora)-2147483647)<br />
<br />
<br />
<br />
<br />
#undef CONST<br />
<br />
#ifdef _olint<br />
# define CONST const<br />
#else<br />
#if defined(PMAX) &amp;&amp; defined(__STDC__)<br />
#&nbsp;  define CONST const<br />
#else<br />
# ifdef M88OPEN<br />
#&nbsp; define CONST const<br />
# else<br />
#&nbsp; ifdef SEQ_PSX_ANSI<br />
#&nbsp;  ifdef __STDC__<br />
#&nbsp; &nbsp; define CONST const<br />
#&nbsp;  else<br />
#&nbsp; &nbsp; define CONST<br />
#&nbsp;  endif<br />
#&nbsp; else<br />
#&nbsp;  define CONST<br />
#&nbsp; endif<br />
# endif<br />
#endif<br />
#endif<br />
<br />
<br />
<br />
#ifdef lint<br />
# define dvoid void<br />
#else<br />
<br />
# ifdef UTS2<br />
#&nbsp; define dvoid char<br />
# else<br />
#&nbsp; define dvoid void<br />
# endif<br />
<br />
#endif<br />
<br />
<br />
<br />
typedef void (*lgenfp_t)(/*_ void _*/);<br />
<br />
<br />
<br />
#include &lt;sys/types.h&gt;<br />
#define boolean int<br />
<br />
<br />
<br />
<br />
#ifdef sparc<br />
# define SIZE_TMAXVAL SB4MAXVAL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />
#else<br />
# define SIZE_TMAXVAL UB4MAXVAL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />
#endif<br />
<br />
#define MINSIZE_TMAXVAL (size_t)65535<br />
<br />
<br />
#endif<br />
]]></description>
         <link>http://www.eygle.com/digest/2008/08/basics-of-c-within-the-oracle.html</link>
         <guid>http://www.eygle.com/digest/2008/08/basics-of-c-within-the-oracle.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Oracle摘</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Oracle</category>
        
         <pubDate>Tue, 19 Aug 2008 17:17:52 +0800</pubDate>
      </item>
      
      <item>
         <title>萝卜治咳嗽 简单有奇效</title>
         <description><![CDATA[　　用萝卜治疗宝宝咳嗽比较简单而且效果奇好，并且没有副作用，宝宝也比较容易接受。用萝卜治疗宝宝咳嗽可以说是一种不可多得的好方法。根据网友反应，这种方法见效比较快，效果也很好。

　　<strong>方法一</strong>：萝卜榨汁，再加上些蜂蜜，搅拌均匀后饮用。

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

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

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

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

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

　　<strong>方法七</strong>：萝卜用榨汁机榨出近300ML的萝卜汁，放一块冰糖（约大拇指大），放在锅里刚刚煮开就行下，放在冰箱里，每天早晚热温了喝50ML，基本上就好了。]]></description>
         <link>http://www.eygle.com/digest/2008/08/luobo.html</link>
         <guid>http://www.eygle.com/digest/2008/08/luobo.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">孕产婴儿</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Baby</category>
        
         <pubDate>Tue, 05 Aug 2008 15:52:13 +0800</pubDate>
      </item>
      
      <item>
         <title>小儿肺炎与气管炎的辨别法</title>
         <description><![CDATA[上呼吸道感染(感冒)是婴儿的常见病。虽然大部分患难与共儿能够痊愈，但有时由于家长的疏忽，也会使用权感冒发展成气管炎以至肺炎。肺炎是婴儿期死亡率较高的一种疾病。必须及早诊断和治疗。气管炎和肺炎的常见症状都是发热、咳嗽和呼吸加快。那么，怎样来辨别这两种疾病呢？

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

<ul>
	<li>　　1-2个月婴儿：呼吸频率大于或等于每分钟60次；</li>
	<li>　　2个月-1岁婴儿：呼吸频率大于或等于每分钟50次</li>
	<li>　　1-3岁婴儿：呼吸频率大于或等于每分钟40次</li>
</ul>；

　　如果婴儿的呼吸次数低于上述标准，只是咳嗽和发热，一般可诊断为气管炎。如果连续两次测定，婴儿的呼吸频率达到或高于上述标准，基本上可判定为肺炎。此时，应立即将孩子送往医院，及时治疗。]]></description>
         <link>http://www.eygle.com/digest/2008/08/baby_kesou.html</link>
         <guid>http://www.eygle.com/digest/2008/08/baby_kesou.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">孕产婴儿</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Baby</category>
        
         <pubDate>Tue, 05 Aug 2008 13:56:19 +0800</pubDate>
      </item>
      
      <item>
         <title>正常体温、高烧与低烧</title>
         <description><![CDATA[<blockquote>体温是指机体内部的温度。正常人腋下温度为30～37度，口腔温度比腋下高0.2～0.4度，直肠温度又比口腔温度高0.3～ 0.5度。</blockquote>

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

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

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

]]></description>
         <link>http://www.eygle.com/digest/2008/08/baby_gaoshao.html</link>
         <guid>http://www.eygle.com/digest/2008/08/baby_gaoshao.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">孕产婴儿</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Baby</category>
        
         <pubDate>Sat, 02 Aug 2008 06:45:21 +0800</pubDate>
      </item>
      
      <item>
         <title>血常规检验之-淋巴细胞比率(LVM%)</title>
         <description><![CDATA[<strong>淋巴细胞正常百分比参考值是20--40％。其比率通常称为LYM%或者LYMPH%、</strong>

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

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

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

淋巴细胞白血病是骨髓及其他造血组织中有广泛的白血病细胞异常增生，主要是不成熟淋巴细胞，及浸润其他组织器官，导致正常造血功能衰竭，表现为正常造血细胞显著减少。与淋巴细胞百分比偏高有关系。确诊需做骨髓穿刺，检查骨髓象。
爱心提示：不排除药物副作用引起。]]></description>
         <link>http://www.eygle.com/digest/2008/08/rt_lym.html</link>
         <guid>http://www.eygle.com/digest/2008/08/rt_lym.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">孕产婴儿</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Baby</category>
        
         <pubDate>Fri, 01 Aug 2008 22:58:58 +0800</pubDate>
      </item>
      
      <item>
         <title>小儿咳嗽多痰的药膳调理</title>
         <description><![CDATA[<strong>咳嗽是小儿呼吸道疾病的常见症状之一，现代医学的急、慢性支气管炎、气管炎、部分咽喉炎均属于此病范围。</strong>中医学按其临床主要症状将咳嗽分为两大类，<strong>一般继发于感冒之后的称为"外感咳嗽"，没有明显感冒症症的称为"内伤咳嗽"</strong>。小儿咳嗽除了要遵医嘱服药外，饮食要清淡、易消化，忌食腥荤辛辣之品。此外，可用下述药膳辅助治疗。
<strong>1、风寒咳嗽：特点是咳嗽，咽痒，咳痰清稀，鼻塞疏清涕等，治疗宜宣肺散寒止咳。</strong>
&nbsp; &nbsp; &nbsp;  (1)紫苏粥：紫苏叶10克，粳米50克，生姜3片，大枣3枚。先用粳米煮粥，粥将熟时加入苏 叶、生姜、大枣，趁热服用。
&nbsp; &nbsp; &nbsp;  (2)葱白粥：大米50克，生姜5片，连须葱白5段，米醋5毫升，加水适量煮粥，趁热饮用。
&nbsp; &nbsp; &nbsp;  (3)杏仁萝卜煎：杏仁(甜)10克，生姜3片，白萝卜100克，水煎服，每日1剂。
&nbsp; &nbsp; &nbsp;  (4)核桃生姜饮：核桃肉5枚捣烂，生姜汁适量送服。
&nbsp; &nbsp; &nbsp;  (5)家庭常备中成药：通宣理肺丸。橘红丸、橘红痰咳液等。

<strong>2、风热咳嗽：特点是咳嗽，痰黄黏稠，鼻流浊涕，咽红口干等。治宜疏风清热，化痰止咳 </strong>。
&nbsp; &nbsp; &nbsp;  (1)二汁饮：鲜藕汁、梨汁等份，生服。
&nbsp; &nbsp; &nbsp;  (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)家庭常备中成药：养阴清肺丸、念慈庵川贝枇杷膏等。]]></description>
         <link>http://www.eygle.com/digest/2008/08/illeating.html</link>
         <guid>http://www.eygle.com/digest/2008/08/illeating.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">孕产婴儿</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Baby</category>
        
         <pubDate>Fri, 01 Aug 2008 21:10:47 +0800</pubDate>
      </item>
      
      <item>
         <title>如何判断是否是病毒性感冒</title>
         <description><![CDATA[<strong>感冒主要有病毒性感冒和细菌性感冒两种</strong>。

一般来讲，如果舌头颜色是深粉红色、白细胞下降的话多是病毒性感冒
舌头颜色是淡粉红色、白细胞上升的话多是细菌性感冒。

因为病毒性感冒可以导致心肌炎、引发肺炎和风湿类疾病，所以感冒后到私人门诊打点滴了事，可能会误将病毒性感冒当成细菌性感冒，从而延误治疗使病情加重。患者需要先判别好感冒类型后再用药，滥用抗生素不但治不好感冒，还会导致体内菌群失调，出现呕吐、恶心等症状，加剧病情。 ]]></description>
         <link>http://www.eygle.com/digest/2008/07/twokindof_ganmao.html</link>
         <guid>http://www.eygle.com/digest/2008/07/twokindof_ganmao.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">孕产婴儿</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Baby</category>
        
         <pubDate>Wed, 30 Jul 2008 12:10:19 +0800</pubDate>
      </item>
      
      <item>
         <title>幼儿病毒性感冒的症状及治疗方法</title>
         <description><![CDATA[<strong>病毒性感冒即上呼吸道感染，又简称上感，是由多种病毒引起的常见呼吸道传染病</strong>。
<strong>诱因</strong>有受寒、淋雨、过度疲劳、营养不良等。

患者的鼻涕、唾液、痰液含有病毒，通过打喷嚏、咳嗽、说话将病毒散播入空气中，感染他人。健康人也可由于接触患者的毛巾、脸盆或餐具等感染病毒而得病。

<strong>感冒主要表现为打喷嚏、鼻塞、流鼻涕、咽干、咽痛、咳嗽、声音嘶哑等症状</strong>。全身表现有<strong>头痛、浑身酸痛、疲乏无力、食欲不振，或不发热，或低热，或高热、畏寒等症状</strong>。病程一般为3天～7 天。感冒发热患者需卧床休息，注意保暖，减少活动。住处要经常通风，保持一定温度和湿度。<strong>多饮开水，吃清淡和稀软的食物。发热较高时可用冷水擦身或温水擦身，水温以32℃～34℃为宜，或30%～50%酒精擦拭颈部、胸部、腋部、腋窝、腹股沟等处，或头枕冰袋</strong>。

<strong>感冒的家庭治疗</strong>：
<strong>多休息、多饮水、注意呼吸道隔离、预防并发症</strong>。常用的抗病毒药有病毒唑,病毒灵,<strong>中药有金银花、板篮根等</strong>,对症药有感冒中成药,一些感冒冲剂,退热药。还有抗病毒滴鼻液,滴眼液等。<strong>感冒的药物治疗并不是很重要的,重要的是护理好,监测体温,防止热惊,让小儿保证充足的睡眠,补充足够的水分和营养, 注意病情的转归,合并症的发生</strong>。因为,<strong>感冒是自限性疾病,病毒在体内有一定的生存期。到病程自然好转</strong>。另外,<strong>一些抗病毒药的疗效也不是很可靠,有的杀伤白细胞,造成白细胞减少,因此,临床上多使用中药清热解毒,如金银花、板篮根等</strong>。症状重的服用一些对症药,如感冒冲剂,退热药。

<strong>发热高并不可怕</strong>：
<strong>感冒发热是小儿机体对感染的微生物的一种反应,是保护性机制</strong>,有的父母,把发热看成是疾病轻重的象征,这是不对的。发热高,并不一定就是病情重, 不发热,或发热轻就是病情轻,一些气管炎、肺炎可能没有体温升高。所以不能把体温作为衡量疾病轻重的指标,退热治疗也不能太急,大多数父母都想马上把体温降到正常,过量服用退热药,小儿出汗过多,机体体温调节中枢紊乱,甚至出现低温,电解质紊乱,这在临床工作中是常见的现象。<strong>退热要缓慢进行,只要把体温控制在高热以下,防止热惊就可以了</strong>。服用退热药时一定要注意水分和电解质的补充,口服退热要与物理降温措施交替使用,特别是<strong>婴幼儿,使用物理降温更好</strong>。还有, <strong>小儿不能象成人那样"捂汗"小儿的体温调节中枢不完善,汗腺发育也不完善,用"捂汗"的方法不但不能使体温下降,还会使体温骤升,出现高热惊厥,尤其是小婴儿,还会出现"蒙被综合征"危及生命</strong>,发热时要少穿、少盖,增加散热。这些都是临床中常常遇到的家庭护理错误。

<strong>不要随便服用抗菌素</strong>：
<strong>人们俗称的感冒就是急性上呼吸道感染,简称上感</strong>。引起上感的病原菌主要是病毒,占90%以上,细菌的原发性感染只占少数。引起上感的常见病毒有呼吸道合胞病毒、流感病毒、副流感病毒、腺病毒、鼻病毒、柯萨奇病毒、埃可病毒、冠状病毒、单纯疱疹病毒、EB病毒。常见的细菌有溶血性链球菌、肺炎球菌、流感嗜血杆菌、肺炎支原体等。<strong>病毒性上感后由于机体抵抗力下降,可继发细菌感染。从感冒的病原体可见,病毒性感冒是占绝大多数。因此,感冒就服用抗菌素, 甚至使用高级抗菌素的做法是不对的</strong>,小儿尤其上小婴儿,上感的几率很大,每次都服用抗菌素,有的连续感冒,连续使用抗菌素,抗菌素越用越高级,结果造成小儿耐药菌生长,一旦有细菌感染,使用药物效果不佳,而且,抗菌素有许多副作用,如杀伤白细胞,使白细胞下降,进一步降低机体的抗病能力,抗菌素对胃肠道黏膜的刺激出现药物性胃炎,肠道菌群失调,长期使用抗菌素,或高级抗菌素,广谱或联合使用抗菌素。使肠道内一些非致病菌被杀灭,出现菌群失调,破坏肠道内微生物平衡,而出现肠道疾病。甚至出现伪膜性肠炎,机会菌--霉菌二重感染,一些非致病菌由于失去了相互制约,而成为致病菌。

在我国,特别是给儿童滥用抗菌素现象非常严重。据有关报道,我国是消耗抗菌素的大国。约占世界消耗量的一半。相当于发达国家使用抗菌素量的十几倍。感冒的90%以上是病毒感染。抗菌素对病毒是无效的,每次感冒都服用抗菌素是不好的。要有细菌感染的证据再投用抗菌素。不要因为怕细菌感染而预防性给药,这是错误观点。抗菌素是杀灭细菌的。<strong>没有细菌使用抗菌素只能杀灭白细胞。抗菌素的半衰期是有限的,最长不过几小时。没有长期作用.</strong>

]]></description>
         <link>http://www.eygle.com/digest/2008/07/baby_ganmao.html</link>
         <guid>http://www.eygle.com/digest/2008/07/baby_ganmao.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">孕产婴儿</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Baby</category>
        
         <pubDate>Wed, 30 Jul 2008 12:04:34 +0800</pubDate>
      </item>
      
      <item>
         <title>唐骏在大连理工演讲两次的经典内容 </title>
         <description><![CDATA[唐骏2008年6月14日在大连理工演讲的具体内容：（以第一人称讲述）

<strong>在北邮追女孩</strong>
你们知道在我们那个上大学的年代不像你们这么丰富多彩。我们那时候除了追女孩外没有什么事情可做。（台下暴笑）你们比我们那时候惨，我们傻，老师让我们学啥我们学啥，也不管有没有用；而你们现在明明知道没有用，却还要学，所以比较郁闷。（支持的掌声）当然，除了大连理工大学的学科除外，因为卢校长在这。（暴笑）你们学的东西几乎没有什么用。（台下再次更暴笑）上大学的我平凡的不能再平凡了，那时候什么都没有，就长成我这样的，基本上不用考虑本班的战场，没有我的立足之地，我就发展别班的战场，我看上了一个女生，据听说还是北邮50校花之一呢。（笑）你们可别小瞧，50校花之一可了不得，当时我们北邮可有156名女孩呢。（全场爆笑）你说我那时是弱势群体，我能做什么呢，我什么都做不了，最后想出了一招我能做的事：写信。第一封我写了身高1米82体重 132斤家在江苏常州，父母是干什么的，家有几个兄弟。这简直就是一份简历，没办法，那时的我没什么只有这些，就给她投了简历。她没有理我。我就开始写第二封信，为了展现自己的才华，我就介绍了一下国内国际经济形势，（台下暴笑）我未来会怎么怎么做。。。还是没回音。我就写了第三封，说我知道你不喜欢我，我不要求你做什么，我只要求你让我默默的喜欢你就好了。（全场暴笑）你知道那时的女生"纯"那！（纯音很重，全场笑）三封信就感动了她，她回信给我。我就约她看电影，看的什么电影我不记得了。之后我们散步，我对她说，要不你嫁给我吧。（全场惊讶）她很惊讶说唐骏你是认真的？我说是，她说好我嫁给你。（更惊讶）就这样，第一次约会，她就嫁给了我，而后我们一起走过了随后的20多个春秋。（全场热烈的掌声）

<strong>争取留学名额</strong>
我那时在北京邮电上学，花了两年时间考研究生，考了全校第一，当时每个重点院校有两个名额可以保送到美国，但我却没被保上。你们知道我当时是弱势群体，没有什么权利，但我不甘心就这样，然后四处打听，打听到北京广播学院（中国传媒大学）还有一个空的名额，我就去北广找老师，说想把学籍从北邮转到北广来。老师说，你为什么要转到北广来，我说为了中国的传播事业，中国的传播事业太落后了，我想尽一份自己的力量。老师说中国的邮电事业比广播事业还要落后，你怎么不推进邮电事业的发展呢。我说我太喜欢广播事业了，想为它献身，那时候的老师"纯"那，（全场爆笑）几句话就被我感动了。老师说好吧。经过复杂的转学手续转到了北广，我就向老师说想出国留学，老师怀疑的说你是不是为了出国才转到北广的？我说不是我想出国学人家先进的技术回来武装中国的广播事业。你们知道，那时候的老师"纯"那，（更暴笑）他相信了。但是他说，申报名额已经交到国家教育局了，时间已经耽搁了。我就去找国家教育部出国留学司司长，他说已经审批完了，现在来不及了。我那时候很失望，但我不想放弃，不想以前的努力就这么白费了。你们知道咱们大学生是弱势群体，什么也改变不了，咱们什么都没有，但有的是时间，于是我就想了一个我能想到的办法，很简单很笨的办法：我开始去国家教育局"上班"，上班地点是教育局门口，（台下狂笑）司长早上来上班的时候，我就迎上去说，司长好，来上班了？中午司长出门去对面食堂吃饭的时候，我就说司长吃饭啦，吃好点哈；司长吃饭回来的时候，我就说，司长吃完了，还有点时间，你可以午睡一会；下午下班的时候我说司长下班了。就这样一天两天，司长很奇怪什么时候教育局门口多了个保安，还只给他打招呼。你们知道，人那，不怕被人恨，被人凶，就怕被人盯上，司长开始不得劲了。我倒无所谓，我还有四个月才毕业，这段时间我正好没地方去，就可以天天到教育厅来"上班"，感觉也都很气派，来国家教育厅上班（台下暴笑）。到第五天的时候，司长撑不住了，中午我照样说，司长吃完啦，还有点时间可以午睡一下。司长说我不午睡了，你跟我上来一下。进了司长办公室，司长问你干吗的，我就说明了原因。司长什么也没说，第六天我照样过去"上班"，中午的时候又被叫进去，司长给了我一堆资料说这些你填一下，我就拿回去填。第七天，司长给了我一张纸，说这是你一直想要的东西，那张纸就是出国留学批准证。（全场爆发出热烈的掌声）大家知道吗，人们需要执着的精神，你就拿出执着的精神给他们看，世上就不怕没有办不成的事。（全场热烈的掌声）

<strong>获选全国十大帅哥CEO</strong>
前一段时间参加鲁豫有约节目，鲁豫说唐骏博士你有这么多头衔我都不知道该叫您哪个，你认为你最重视的，最有价值的是哪个。我说我最有的价值的最有含金量的那个你介绍我时没说出来。鲁豫很奇怪，是哪个？前一阵我被时尚杂志评为全国十大帅哥CEO。这是我认为最有含金量的一个（全场爆笑）。我被评为过全国十大经济人物，全国十大CEO，只要经济方面有关十大的我都被评过，就是时尚方面还是第一次。像我这种没有貌的人能被评为帅哥，我能不激动嘛，这是我人生的一次里程碑，我得感谢我的爸爸妈妈。（全场笑）

<strong>在微软的差异化竞争</strong>
我进入微软以后，在一万五千人中是倒数第一，在技术方面是最差的，我若在技术上与他们竞争，过二十年三十年我也不过是个普普通通的人，顶多是个高级工程师。我想应该避开和他们正面竞争，走差异化竞争路线。在那五个月后发现开发模式上的错误，英文版本开发出来后，需要过八个月中文版本才开发出来，过五个月日语版本才开发出来。好多人都注意到这个问题，也有好多人提出来许多书面方案交给经理，将近有八十多份，但是你想想你要作为那个经理，你会看这么多的方案吗？所以，交书面方案效果甚微，我就想如果我自己解决了这个问题，即找到了方法也找到了技术支持，那样就很有效果了。然后我就开始发挥我勤奋的因素，利用晚上和周末的时间分析这三种版本的共同之处和不同之处，找出一种模式可以将三种不同版本都用这一模式进行开发，又找到了技术支持，然后写了一份书面报告，不仅提出这个问题也解决了这个问题，我将编的程序都放在这里面了。经理开会议一致通过了该方案，决定公司3500个人都使用这种研发模式，这样就需要成立一个宣传部门，在公司宣传这种模式，我称之为唐氏研发模式，理所当然的候选人就我一个，没有竞争对手，就在我刚进入微软八个月后就当上了部门经理。（热烈的掌声起。。。）这就是我要讲的差异化竞争。


<strong>运用与众不同的商业模式</strong>
我在洛杉矶开了一家第一移民律师事务所，我是计算机博士出身，对法律一点都不明白，光是有关的法律书就有一米这么高。我注意到别家事务所都是按小时收费，有时移民采用打电话的方式，一个小时都问不明白，但钱却搭进去了，让人感觉移民咨询像个无底洞，不知到得花多少钱才能办成。我就采用和别家事务所不一样的商业模式：我是按案例收费，如工作卡转签证收1000美金，签证转绿卡600美金等，还有最重要的一句：不成功不收费，成功了再收费。这样就在洛杉矶一炮打响，我的第一移民律师事务所在开业五个月后就排洛杉矶第一位。（热烈的掌声起。。。）我告诉大家接下来的两年内我准备做一件事情，我从未涉足的领域，电影事业，（台下一片惊讶），别惊讶，谁让我爱好广泛呢。。（台下哈哈大笑）中国好电影这么多，我的电影肯定做不成功，但我想运用一种和他们不同的商业模式，现在电影宣传力度很大，但许多观众看完后都会失望，好多人就自己买碟看，不再去电影院看电影。我不会请大腕明星，砸很多钱进去，我会采用就和我刚才讲的在洛杉矶开律师事务所一样的商业模式，就是满意了收钱，不满意可以退票。当然我有满意的标准的，我会在每个电影放映室里笑声安计数器，如果70%以上的大家都笑了，那他会记一，然后记二。我要拍喜剧片，励志型的外资喜剧片，我希望电影所达到的效果让观众笑二十次，如果观众没有笑二十次，那么观众可以退票，我们会无条件接受。（好方法，真的与众不同）当然我们拍片就得拍的很好看，有很高的标准。

<strong>八卦故事</strong>
现在我将给大家一个特八卦的故事。这个故事我讲给了两个人听。一个是盖茨，他非常相信；另一个是朱镕基，他一点都不相信。所以在场的大家不用担心，你若相信，说不定你就是下一个盖茨，你若不相信，你或许就是下一个朱镕基。（全场笑）我讲的这个八卦故事，你们要是相信，就是未来的宏观经济学家。在1985年的时候日本经济各个指数突然飘红，经济形势一片大好，据当时经济学家预计照这种形势发展下去，到2012年日本就会在各个方面超过美国，成为世界第一超级大国。许多经济学家找不到快速发展的原因所在，令人很费解，你们知道为什么吗?(台下一片疑惑)因为那时候有个年轻人到了日本。（噢。。。台下恍然大悟，许多人笑了起来，但还有些人不明白）后来90年几月份，日本经济萎靡不振，持续五年的增长突然停滞不前，而这时美国的经济从萎靡中摆脱出来开始快速增长，道格拉斯指数一天涨了28.3%，全世界的经济学家都无法解释这个原因，感觉很奇怪，你们又知道为什么吗？只有我知道，那时候有一个年轻人离开日本去了美国。不用我说你们知道那人是谁了吧。（我们恍然大悟）我把这个故事讲给盖茨后，问他微软从什么时候出现转折快速增长的，盖茨说94年几月份，他说不会你那时来的微软吧。我说你猜对了，然后盖茨目瞪口呆的盯着我。。。后来我告诉朱镕基总理这个八卦的故事后问他：中国经济什么时候开始快速发展的，总理说97年下半年吧，他说你不会那时回的国吧，我就告诉总理是97年下半年回的国。总理急忙说：这跟你没关系，是这届中央政府领导的好。总理果然是总理，什么事都会往政府上靠。（台下暴笑）
97年我要离开微软的时候，写了一封很长的信给盖茨，据听说很煽情，（台下笑）我也给公司每个员工都发了一份，因为我是计算机出身，所以会COPY很多份。（暴笑）好多员工都哭了，信中我记得有这么一段：在微软的几年里，我不敢说我是微软最勤奋的员工，但我敢说微软里没有比我更勤奋的员工。（台下一片钦佩和笑声））两句一个意思哈。很快盖茨打电话给我：骏（特深情），你一定要走吗？我说：比尔，我一定要走。"你真的不可以留下吗，我可以给你任何位置，随便你选。"（任何位置但不包括盖茨的那个位置哈（全场暴笑））"我离开中国太久了，我得回去参加祖国的建设。""那好吧"。随后盖茨立即召开董事会会议，会上全体一致同意授予唐骏微软终身荣誉总裁称号。这是历史上唯一的一个微软终身荣誉总裁称号，以前没有，以后也不会再有了，你们知道为什么吗？就因为我曾经给盖茨讲了一个八卦的故事。。。授予我终身荣誉总裁，盖茨就可以一辈子把我留在微软了（全场爆笑加特热烈的掌声）我现在哪都不敢去，大家都知道，其实宏观经济给我没啥关系，但我就怕离开了中国，中国万一出点啥事，那我可就是千古罪人了。（台下暴笑）我可以负责任的告诉大家，未来50年我不会再离开中国！（台下热烈的鼓掌）


<strong>劝盖茨改行程</strong>
2003年我接到盖茨秘书打来的电话，她说盖茨要在2月几号来中国，我大吃一惊，也很惊喜，你们知道吗，我在中国当微软总裁，副总理谁都可以见，就是江主席见不着，盖茨来中国会和江主席见面，我高兴的不是盖茨来中国，是我可以见着江主席了。（台下狂笑）但算了一下，那一天正好是大年初三，和江主席见面可能有麻烦。我就告诉秘书说不行，那天大年初三盖茨不能来。你们知道有种人地位不高，但权力很大，（全场笑）秘书很生气说你竟然敢说不，你可知道盖茨的行程都是一年前安排好的。（台下一片惊讶声）是，我知道，可是那天来会有麻烦，会面不会顺利。你自己跟盖茨谈吧。我就打电话给盖茨，告诉他那天不能来中国，他很惊讶，说你可知道我的行程都是一年前安排好的。你们知道盖茨脾气很大，不是，应该说他是很有"个性"的一个人。（台下狂笑，暗指他脾气很大）。我说，我知道，你的行程是一年前安排好的，可是中国的春节是5000年前就安排好的。（全场鼓掌）盖茨更惊讶了。你想想美国人听到5000年是什么概念，盖茨得惊讶成什么样。（台下一片笑声）就这样盖茨同意改了行程。后来盖茨来中国，我到首都国际机场迎接的时候，盖茨见着我第一句话就是，你好大胆，这是我进入微软 36年来第一次改行程。我说你不是输给了我，你是输给了中国5000年的文化。你看这样说，立马抬高了老板的地位，和5000年挂上了钩。（笑声掌声起）


<strong>盖茨口头语"That's good!"</strong>
在中南海盖茨和江主席会面，我在旁边给盖茨说，现在正是中央换届的敏感时期，你要做的就两件事情，一个光听江主席讲就行，不要插嘴；还有一个你的改改你的口头语。你们知道，和盖茨说过话的人都知道他有一句口头禅"That's good!"他想表达的意思是鼓励对方继续讲下去，我在听的意思。盖茨说这是从小的习惯我改不了，我说无论如何你得改，盖茨坚持说我改不了。我就说，你听江主席讲话的时候看我，你看我总不至于会说"That's good"。见着江主席的时候，江主席拉着盖茨的手说：盖茨啊，你知道再过五天我就要辞去中国最高领导人的职位，由下一届领导班子接任。。。。你们知道我那时候最害怕什么吗？就怕盖茨嘴里蹦出一句"That's good！"（全场爆笑）要是这样就闹出世界性的政治丑闻了。]]></description>
         <link>http://www.eygle.com/digest/2008/07/king_of_work.html</link>
         <guid>http://www.eygle.com/digest/2008/07/king_of_work.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">人物传奇</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Microsoft</category>
        
         <pubDate>Sun, 20 Jul 2008 21:54:26 +0800</pubDate>
      </item>
      
      <item>
         <title>Solaris的动态ISM共享内存</title>
         <description><![CDATA[<strong>4.4.3 动态ISM共享内存</strong>
动态紧密共享内存（DISM）最早是在Solaris 8 1/01版本（第三个更新版）中引进的，其目的是为了给应用程序提供动态可变大小的ISM共享内存。<strong>第一个支持DISM的主要应用程序是Oracle 9i。Oracle 9i使用DISM是为了它新引入的动态系统全局区域（SGA、System Global Area）功能</strong>。

<strong>对于普通的 ISM，一旦ISM块被生成，则不可能去改变它的大小。为了改变数据库缓冲区的尺寸，数据库必须关闭再重启（或设计为使用一组可变数量的共享内存块----这是一种更为复杂的替代方法）</strong>。这种限制对系统可用性有负面影响，例如，如果内存由于动态重新配置事件而被系统删除，一个或多个数据库实例会不得不关闭。 DISM就是为了克服这种限制而设计的。<strong>当数据库启动时，会生成一个较大的DISM内存块，其中的各段可以随着内存需求的变化而选择性的被加锁、解锁。为 DISM内存加锁不是由内核自动完成的，而是由应用程序（例如，Oracle）进行加锁、解锁，这样为动态调整提供了灵活性</strong>。
除了DISM不像ISM那样自动加锁外，DISM与ISM大体相似的。是由应用程序，而不是内核通过调用mlock()进行锁操作。内核的虚存-物理内存地址转换结构由附加在DISM内存块的进程共享，这样可以节省内核存储空间和CPU时间。

<strong>4.4.3.1 DISM性能</strong>
<strong>这个Solaris版本中测试表明，DISM和ISM性能相当。这是一个重要的进展，因为这意味着DISM在可用性上的改进，而不会在性能上有任何的损失。</strong>

4.4.3.2 DISM实现

使用ISM机制，shmget（2）生成内存块。shmget()所指定的大小是整个内存块的大小，也就是最大尺寸。内存块的大小可以大于物理内存。如果内存块尺寸比物理内存块大，那么就应该有足够的磁盘交换空间来满足最大可能的DISM尺寸。

DISM内存块通过shmat（2）接口，被附加到某个进程。新标志位SHM_DYNAMIC，通知shmat（2）生成动态ISM。物理内存是根据访问所需要的页面大小来分配，或者是根据在DISM虚拟区域中加锁所需要的页面大小来分配。

来源：<a href="http://book.51cto.com/art/200709/56908.htm">51CTO</a>
出自图书：<a href="http://www.china-pub.com/34295">Solaris Internal</a>。

]]></description>
         <link>http://www.eygle.com/digest/2008/07/solaris_ism.html</link>
         <guid>http://www.eygle.com/digest/2008/07/solaris_ism.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Oracle摘</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Oracle</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">Solaris</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">Unix</category>
        
         <pubDate>Sun, 20 Jul 2008 20:36:19 +0800</pubDate>
      </item>
      
      <item>
         <title>Oracle服务费的计算方式</title>
         <description><![CDATA[根据Oracle公司的销售政策，假如以Oracle11g产品为例，目前11g的报价是： 单cpu 4w美金；按用户算是800美金；
如果用户按照CPU方式购买： 2 CPU的一台服务器部署：8W美金，这个是购买价格；然后用户每年需要支付22％的服务费；即8W×22％＝1.76W，就是说，Oracle即便不给用户干任何活，用户每年也得向它支付1.76w美金。考虑折扣因素，实际价格应该在 30--40%。

Oracle公司销售服务的类别大致有以下几种：
A.基本服务：都是远程的，电话，网上支持，不一定都能解决。续保（PS）: 基本服务续上。
B.高级服务（ACS）: 除了基本服务，现场，安装，技术交流，故障排查。
C.小单续保（CRS）：服务费是25K美金以下，采用电话销售。
___License100万= （ 25k*8*( 1+17%) ）/ 22% 这个公式是表示服务费和产品销售额之间的关系。
D.外包服务（On Demand）: ERP 方面为主，以厂商为主去做用户服务，不管License什麽的。
F.延伸服务:在标准服务的基础上，产品上市第6年加10%服务费，第7年加20%服务费，第8年加20%，再往下还是加20%服务费。

数据库版本中的9i产品到第6年的从07年8月1日到08年7月31日，对中国客户免掉10%的服务费。

来源：<a href="http://tech.it168.com/db/2008-04-07/200804071645500_1.shtml">IT168</a>]]></description>
         <link>http://www.eygle.com/digest/2008/07/oracle_service_fee.html</link>
         <guid>http://www.eygle.com/digest/2008/07/oracle_service_fee.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Oracle摘</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Oracle</category>
        
         <pubDate>Thu, 17 Jul 2008 21:26:36 +0800</pubDate>
      </item>
      
      <item>
         <title>Oracle Dataguard三种保护模式概述</title>
         <description><![CDATA[Oracle的DataGuard技术有三种实现模式，分别是max performance、max availability、max protection这三种模式。

以下是来自Oracle文档的摘要信息：
In some situations, a business cannot afford to lose data. In other situations, the availability of the database may be more important than the loss of data. Some applications require maximum database performance and can tolerate some small amount of data loss. The following descriptions summarize the three distinct modes of data protection.

Maximum protection This protection mode ensures that no data loss will occur if the primary database fails. To provide this level of protection, the redo data needed to recover each transaction must be written to both the local online redo log and to the standby redo log on at least one standby database before the transaction commits. To e