home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Kernel / BootCode / bootKernel.c
Encoding:
C/C++ Source or Header  |  1990-08-17  |  12.7 KB  |  444 lines

  1.  
  2. /*
  3.  * $Header: ~eden/Kernel/DataStructs/bootKernel.c Rev. 1.0 11-Jun-85$
  4.  *
  5.  * $Log:$
  6.  * Revision 2.0 June 1986 eric
  7.  * Modified extensively for Emerald.
  8.  *
  9.  * Revision 1.0 11-Jun-85 oystr
  10.  * Routines which perform the kernel boot protocol.  Derived from
  11.  * the original which was in initHots.c.
  12.  *
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include "Kernel/h/timerTypes.h"
  17.  
  18. #ifdef xkernel
  19. #include "userupi.h"
  20. #endif
  21.  
  22. #include "Kernel/h/system.h"
  23. #include "Kernel/h/assert.h"
  24. #include "Kernel/h/stdTypes.h"
  25. #include "Kernel/h/mmCodes.h"
  26. #include "Kernel/h/errMsgs.h"
  27. #include "Kernel/h/mmTypes.h"
  28. #include "Kernel/h/mmMsgTypes.h"
  29. #include "Kernel/h/kBootCodes.h"
  30. #include "Kernel/h/kEvents.h"
  31. #include "Kernel/h/dstCodes.h"
  32. #include "Kernel/h/hotsTypes.h"
  33. #include "Kernel/h/kBootTypes.h"
  34. #include "Kernel/h/kmdTypes.h"
  35.  
  36. extern void         AddHOTS(), ChangeHOTS();
  37.  
  38. extern KKStatus     HOTSSearchPtr();
  39. extern time_t       nodeIncarnationId;
  40. extern char        *mGetHostName();
  41. extern EtherNetAddress MMLocalEtherNet;
  42. extern long         random();
  43. extern char        *ctime();
  44.  
  45. /* Forward declaration of snapshot */
  46. /* Forward */ void                SendAlive();
  47.  
  48. /*
  49.  * Time to wait (in seconds) for replies to our broadcast
  50.  * announcement that we are booting.
  51.  */
  52.  
  53. #define STARTWAIT 4
  54.  
  55. /*
  56.  * Global copy of node characteristics bit map.
  57.  */
  58. BitMap32 MyNodeType;
  59.  
  60. /*
  61.  * "forward" declarations for Message Handlers.
  62.  */
  63. HResult StartUpHandler(), ShutDownHandler(),
  64.         SendStartUp(), BcastHandler();
  65.  
  66. /***********************************************************************/
  67.  
  68. BootKernel(nodetype)
  69. BitMap32 nodetype;
  70. {
  71.   extern int srandom();
  72.   TimerId dummy;
  73.         
  74.   KMDSetSnap(SendAlive);
  75.  
  76.   MyNodeType = nodetype;
  77.  
  78.   /*
  79.    * Get ready to handle all those replies we expect to our broadcast.
  80.    * Also handle startup messages from other booting nodes.
  81.    */
  82.   MMDefineMsgHandler(KMSG_Boot, BOOTM_Reply, (HandlerPtr) StartUpHandler,
  83.     (HandlerPtr *)NULL);
  84.   MMDefineMsgHandler(KMSG_Boot, BOOTM_StartUp, (HandlerPtr)StartUpHandler,
  85.     (HandlerPtr *)NULL);
  86.   MMDefineMsgHandler(KMSG_Boot, BOOTM_ShutDown, (HandlerPtr)ShutDownHandler,
  87.     (HandlerPtr *)NULL);
  88.   MMDefineMsgHandler(KMSG_Boot, BOOTM_Broadcast, (HandlerPtr) BcastHandler,
  89.     (HandlerPtr *)NULL);
  90.  
  91.   /*
  92.    * Initialize our BackOff generator.
  93.    */
  94. #ifdef xsimul
  95.   srandom( (int)(getpid() ^ time((time_t *) 0)) );
  96. #else
  97.   srandom( (int)(314 ^ time((time_t *) 0)) ); /* anyone for some pi? */
  98. #endif
  99.   /*
  100.    * Put ourselves in the HOTS.
  101.    * MM will fill in ethernet address (FIXME - a dangerous assumption).
  102.    *
  103.    */
  104.   DebugMsg(5, "adding self to hots\n");
  105.   AddHOTS(MMLocalEtherNet, GetLNN(), nodetype, Booting,
  106.       nodeIncarnationId);
  107.  
  108.   /*
  109.    * Send out a broadcast describing ourselves, and asking for
  110.    * information about other nodes.
  111.    */
  112.   DebugMsg(5, "Sending boot message\n");
  113.   SendBootMsg(GetLNN(), NULLNODE, MMLocalEtherNet,
  114.           MyNodeType, (MessageSubtype) BOOTM_Broadcast);
  115.  
  116.   /*
  117.    * After a suitable delay, send out the startup message.
  118.    */
  119.   MMSetTimer(STARTWAIT, (HandlerPtr)SendStartUp, 0, &dummy);
  120. }
  121.  
  122. /***********************************************************************/
  123.  
  124. HResult SendStartUp()
  125. {
  126.   /*
  127.    * Change ourselves from Booting to Alive.
  128.    */
  129.   ChangeHOTS(GetLNN(), Alive);
  130.   printf("  Kernel fully booted.\n");
  131.  
  132.   /*
  133.    * Send out a StartUp message, to tell everyone we've finished
  134.    * booting.
  135.    */
  136.   SendBootMsg(GetLNN(), NULLNODE, MMLocalEtherNet,
  137.           MyNodeType, (MessageSubtype) BOOTM_StartUp);
  138. }
  139.  
  140. /***********************************************************************/
  141. /* Routine to Broadcast a message saying that I am alive.              */
  142. /***********************************************************************/
  143.  
  144. HResult SendAliveMsg()
  145. {
  146.     KMDTrace("HOTSUpDown", 3, "Broadcasting Alive: LNN %d of %.15s\n",
  147.     GetLNN(), 4+ctime(&nodeIncarnationId));
  148.     SendBootMsg(GetLNN(), NULLNODE, MMLocalEtherNet, MyNodeType,
  149.         (MessageSubtype) BOOTM_StartUp);
  150. }
  151.  
  152. /***********************************************************************/
  153. /* Snapshot to Broadcast a message saying that I am alive.              */
  154. /***********************************************************************/
  155. /* Snapshot */ 
  156. void SendAlive()
  157. {
  158.     SendAliveMsg();
  159. }
  160.  
  161. /***********************************************************************
  162.  * Routine to send out a broadcast telling an imposter to die.
  163.  * Retransmistted to ensure that it gets through
  164.  */
  165.  
  166. void KillImposter( fMsg )
  167. MessagePtr fMsg;
  168. {
  169.   EtherNetAddress theEtherAddr;
  170.  
  171.   bcopy((char *)&fMsg->MsgHdr.SrcSinAddr, (char *)&theEtherAddr.sin_addr, 4);
  172.  
  173.   /* Kill the imposter by sending out an I am alive broadcast */
  174.   KMDTrace("HOTSUpDown",4,"Sending Alive msg to imposter LNN %d of %.15s at %s\n",
  175.        fMsg->MsgHdr.MsgSrc, 4+ctime(&fMsg->MsgHdr.SrcIncarnationId),
  176.        mGetHostName(& theEtherAddr));
  177.  
  178.   SendBootMsg(GetLNN(), NULLNODE, MMLocalEtherNet, MyNodeType,
  179.           (MessageSubtype) BOOTM_StartUp);
  180.  
  181.   /* Set a couple of timers so that we are sure to get him */
  182.   MMSetMicroTimer(1, 0, (HandlerPtr)SendAliveMsg, 0, (TimerId *)NULL);
  183.   MMSetMicroTimer(5, 0, (HandlerPtr)SendAliveMsg, 0, (TimerId *)NULL);
  184. }
  185.  
  186. /***********************************************************************
  187.  * Generate a "random" waiting time before we respond to a node's
  188.  * booting message.  We don't want to overwhelm the node with replies.
  189.  */
  190.  
  191. integer BackOff()
  192. {
  193.     integer result;
  194.     assert(STARTWAIT > 2);
  195.     result = ((integer) random() & 0x7FFFFFF) % (1000000 *( STARTWAIT - 2));
  196.     return( result+200 );
  197. }
  198.  
  199. /***********************************************************************/
  200.  
  201. /*ARGSUSED*/
  202. HResult SendBootReply( fNewNode, fTimerId )
  203.     NodeNum fNewNode;
  204.     integer fTimerId;
  205. {
  206.     KMDTrace("HOTSUpDown", 4, "Replying to node %08x boot msg.\n",fNewNode);
  207.     SendBootMsg( GetLNN(), fNewNode, MMLocalEtherNet,
  208.              MyNodeType, (MessageSubtype) BOOTM_Reply);
  209. }
  210.          
  211. /***********************************************************************/
  212. /*
  213.  * Send out a reply to a bootup broadcast message.
  214.  */
  215. HResult BcastHandler(fMsg)
  216. GenericKBootMsg *fMsg;
  217. {
  218.   BootMsg *bmp;
  219.   integer delay;
  220.   KKStatus lStatus;
  221.   TimerId dummy;
  222.  
  223.   bmp = &fMsg->Msgunion.Boot;
  224.  
  225.   KMDTrace("HOTSUpDown", 4, "BcastHandler: node %d booting, incarnationId %.15s\n",
  226.        bmp->nodenum, 4+ctime(&fMsg->MsgHead.SrcIncarnationId));
  227.  
  228.   AddHOTS(bmp->nodeaddr, bmp->nodenum, bmp->nodetype, Booting,
  229.       fMsg->MsgHead.SrcIncarnationId);
  230.  
  231.   /*
  232.    * Don't deluge the booting node with a lot of replies at
  233.    * the same time.  Try to distrubute them a little more
  234.    * randomly.
  235.    */
  236.   delay = BackOff();
  237.   lStatus = MMSetMicroTimer( (int)(delay/1000000), (int)(delay % 1000000),
  238.                 (HandlerPtr)SendBootReply, bmp->nodenum, &dummy );
  239.   if ( ! mSUCCESS( lStatus ) ) {
  240.     ErrMsg("Can't set boot backoff: %08x.\n",lStatus);
  241.     SendBootMsg(GetLNN(), bmp->nodenum, MMLocalEtherNet,
  242.             MyNodeType, (MessageSubtype) BOOTM_Reply);
  243.   } else
  244.     KMDTrace("HOTSUpDown", 5, "Boot reply delay: %d.\n",delay);
  245.  
  246.   /*
  247.    * Should also send info about other nodes we know about here.
  248.    */
  249.   MMDeallocateMsg((MessagePtr)fMsg);
  250. }
  251.  
  252. /***********************************************************************/
  253. /* Send a boot reply to someone we just declared to be up              */
  254. /***********************************************************************/
  255. void ScheduleBootReply(fLNN)
  256. NodeNum fLNN;
  257. {
  258.   int delay;
  259.   TimerId dummy;
  260.   KKStatus lStatus;
  261.  
  262.   /*
  263.    * Don't deluge the booting node with a lot of replies at
  264.    * the same time.  Try to distrubute them a little more
  265.    * randomly.
  266.    */
  267.   delay = BackOff();
  268.   lStatus = MMSetMicroTimer( (int)(delay/1000000), (int)(delay % 1000000),
  269.                 (HandlerPtr)SendBootReply, fLNN, &dummy );
  270.   if ( ! mSUCCESS( lStatus ) ) {
  271.     ErrMsg("Can't set boot backoff: %08x.\n",lStatus);
  272.     SendBootMsg(GetLNN(), fLNN, MMLocalEtherNet,
  273.             MyNodeType, (MessageSubtype) BOOTM_Reply);
  274.   }
  275.   else
  276.     KMDTrace("HOTSUpDown", 5, "Boot reply delay: %d.\n",delay);
  277. }
  278.  
  279.  
  280.  
  281. /***********************************************************************/
  282. /*
  283.  * Add a node to the HOTS as a result of getting a startup message.
  284.  * Note that this message is broadcast and we rely on the fact that
  285.  * the message module filters out our own broadcasts (which we WILL
  286.  * receive).
  287.  */
  288.  
  289. HResult StartUpHandler(fMsg)
  290. GenericKBootMsg *fMsg;
  291. {
  292.   BootMsg *bmp;
  293.   HOTSRecord *hp;
  294.  
  295.   bmp = &fMsg->Msgunion.Boot;
  296.  
  297.   KMDTrace("HOTSUpDown",4,"StartUpHandler: node %d now Alive\n", bmp->nodenum);
  298.  
  299.   if ( ( fMsg->MsgHead.MsgSubtype == BOOTM_Reply )
  300.       && (bmp->nodenum == GetLNN()) ) {
  301.     /*
  302.      * Make sure we aren't trying to impersonate somebody
  303.      * else.
  304.      */
  305.     ErrMsg(">>> Boot Panic - Duplicate LNN %04x.\n", bmp->nodenum);
  306.     ErrMsg(">>> I'm @ %s\n",
  307.        mGetHostName((EtherNetAddress *) &MMLocalEtherNet.sin_addr));
  308.     ErrMsg(">>> It's @ %s\n",
  309.        mGetHostName((EtherNetAddress *) &bmp->nodeaddr));
  310.     ErrMsg(">>> Detected by LNN %d.\n",fMsg->MsgHead.MsgSrc);
  311.     ErrMsg(">>> Duplicate node during boot protocol...\n");
  312.     ErrMsg(">>> Shutting down.\n");
  313.     exit( 1 );
  314.   }
  315.  
  316.   if ( mSUCCESS( HOTSSearchPtr(bmp->nodenum, &hp) ) &&
  317.       hp->NodeStat == Booting ) {
  318.     /* The node is going from Booting to Alive. */
  319.     ChangeHOTS(hp->LNN, Alive);
  320.   } else {
  321.     /* We missed the booting msg and/or a shutdown msg. */
  322.     AddHOTS(bmp->nodeaddr, bmp->nodenum, bmp->nodetype, Alive,
  323.         fMsg->MsgHead.SrcIncarnationId);
  324.   };
  325.   MMDeallocateMsg((MessagePtr)fMsg);
  326. }
  327.  
  328. /***********************************************************************/
  329. /*
  330.  * Mark a node dead as a result of getting a shutdown message.
  331.  * Also call other routines interested in knowing about node death.
  332.  */
  333. HResult ShutDownHandler(fMsg)
  334. GenericKBootMsg *fMsg;
  335. {
  336.     BootMsg *bmp;
  337.  
  338.     bmp = &fMsg->Msgunion.Boot;
  339.     KMDTrace("HOTSUpDown", 4, "ShutDownHandler: node %d shutting down\n", bmp->nodenum);
  340.     ChangeHOTS(bmp->nodenum, Dead);
  341.     MMDeallocateMsg((MessagePtr)fMsg);
  342. }
  343.  
  344. /***********************************************************************/
  345. /*
  346.  * Broadcast a shutdown message.  Called by main when a crash is imminent.
  347.  */
  348. SendShutDownMsg(fLNN)
  349. NodeNum fLNN;
  350. {
  351.     SendBootMsg(fLNN, NULLNODE, MMLocalEtherNet,
  352.         MyNodeType, (MessageSubtype) BOOTM_ShutDown);
  353. }
  354.  
  355. /***********************************************************************/
  356. /*
  357.  * Send out a boot message.  "From" is not necessarily us, if we have
  358.  * knowledge of some other node.
  359.  */
  360.  
  361. /*ARGSUSED*/
  362. static SendBootMsg(from, to, nodeaddr, nodetype, mtype)
  363.     NodeNum from, to;
  364.     EtherNetAddress nodeaddr;
  365.     BitMap32 nodetype;
  366.     MessageSubtype mtype;
  367. {
  368.     GenericKBootMsg *fMsg;
  369.     BootMsg *bmp;        
  370.  
  371.     (void) MMAllocateMsg(sizeof( BootMsg ), (MessagePtr *)&fMsg);
  372.     bmp = &fMsg->Msgunion.Boot;
  373.     mEtherCopy(&nodeaddr, &(bmp->nodeaddr));
  374.     bmp->nodenum = from;
  375.     bmp->nodetype = MyNodeType;
  376.     MMBuildMsg((MessagePtr)fMsg, KMSG_Boot, mtype, to, sizeof( BootMsg) );
  377.     if (to == NULLNODE)
  378.         (void) MMBroadcastMsg((MessagePtr) fMsg);
  379.     else
  380.         (void) MMSendMsg((MessagePtr) fMsg);
  381.     MMDeallocateMsg((MessagePtr)fMsg);
  382. }
  383.  
  384. #ifdef DEFUNCT
  385.  
  386. /****************************************************************
  387.  *         Handle Node Status Requests            *
  388.  * This code is pretty much defunct.  It used to be used by    *
  389.  * the old 'whatsup' utility.                    *
  390.  ****************************************************************/
  391.  
  392. HOTSRecord *HOTSTraverse();
  393.  
  394. StatusHandler( fMsg )
  395.     GenericKBootMsg *fMsg;
  396. {
  397.     NetStatusMsg *nsmPtr;
  398.     GenericKBootMsg fullReply;
  399.     NetStatReplyMsg *statReply;
  400.     integer hIndex;
  401.     integer hPlace;
  402.     HOTSRecord *hEntry;
  403.     EdenPort replyPort;
  404.     integer nIndex;
  405.     KKStatus lStatus;
  406.     
  407.     hPlace = 0;
  408.     hIndex = -1;
  409.     nIndex = 0;
  410.     statReply = &fullReply.Msgunion.NetStatReply;
  411.     statReply->nodesIknow[0].thisNode = NULLNODE;
  412.     nsmPtr = &fMsg->Msgunion.NetStatus;
  413.     KMDTrace("HOTSUpDown", 5,"Received BOOTM_NetStatus.\n");
  414.     MMBuildMsg(&fullReply, KMSG_Boot, BOOTM_NetStatReply, GetLNN(),
  415.            sizeof( NetStatReplyMsg ) );
  416.  
  417.     while ( ( (hEntry = HOTSTraverse( &hIndex, &hPlace ) ) != NULL )
  418.         && (nIndex < NODESPERSTATMSG) ) {
  419.     statReply->nodesIknow[nIndex].thisNode = hEntry->LNN;
  420.     statReply->nodesIknow[nIndex].statTime = hEntry->LastMsgTs;
  421.     mEtherCopy(&(hEntry->EtherAddr),
  422.            &(statReply->nodesIknow[nIndex].netAddr));
  423.     statReply->nodesIknow[nIndex].thisStat = hEntry->NodeStat;
  424.     nIndex++;
  425.     }
  426.     if ( nIndex < NODESPERSTATMSG )
  427.     statReply->nodesIknow[nIndex].thisNode = NULLNODE;
  428.     
  429.     lStatus = MMConnectPort(nsmPtr->replyTo, &replyPort);
  430.     if ( !mSUCCESS( lStatus ) ) {
  431.     KMDTrace("HOTSUpDown", 2, "Can't connect to NetStat reply port (%08x): %s.\n",
  432.          lStatus, nsmPtr->replyTo);
  433.       goto exit_label;
  434.     }
  435.     lStatus = MMSendSynchMsg( replyPort, &fullReply, NULL );
  436.     if ( !mSUCCESS( lStatus ) ) {
  437.     KMDTrace("HOTSUpDown", 2,"Can't send NetStat reply (%08x): %s.\n",
  438.          lStatus, nsmPtr->replyTo);
  439.     }
  440. exit_label:
  441.     (void) MMDeallocateMsg( fMsg );
  442. }
  443. #endif DEFUNCT
  444.