vxColor.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:29k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* vxColor.c -  Graph coloring program to demo some vxWorks capabilities */
  2. /* Copyright 1995 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01d,14jun95,rhp fixed some typos in names and comments
  7. 01c,xxapr95,jco took care of colin's notes:
  8. 1- use of a binary semaphore to suspend processNodes instead of
  9.    using taskDelay.
  10. 2- use of a mutex semaphore to suspend the activities while 
  11.    adding new connection(s) or when asking for the net state.
  12. 3- rewrite according to WRS Coding Conventions
  13. 4- mods of the nodeJob interface to hide the database 
  14.    implementation (as an array) behind a pointer.
  15. 01b,xxapr95,jco ported to vxWorks. 
  16. 01a,xxapr95,jco written.
  17. */
  18. /*
  19. DESCRIPTION
  20. Perform the following steps to run the graph-coloring demo:
  21. (1) Call graphInit() to start up the package.
  22. (2) Create and stabilize the graphs for a preconfigured scenario, as
  23. in one of the following examples:
  24. For a simple unconnected collection of map nodes:
  25. .CS
  26. colTest(1);
  27. colTest(2);
  28. .CE   
  29. For a collection of nodes forming a wheel:
  30. .CS
  31. colTest(3);
  32. colTest(4);
  33. .CE
  34. For a collection of nodes with the connectivity of a map of France:
  35. .CS
  36. colTest(5);
  37. colTest(6);
  38. .CE
  39. (3) To display the current map (the argument 2 means to produce a full
  40. display):
  41. .CS
  42. graphDisp(2);
  43. .CE
  44. (4) To change the color of any node (where the <mode> argument
  45. specifies whether to use the <color> argument or generate a random
  46. color):
  47. .CS
  48. colorChange(<nodeId>, <mode>, <color>);
  49. .CE
  50. If <mode> is 1, the new color is random; if <mode> is 2, the color is changed
  51. to the value specified with the <color> argument.
  52. (5) To extend the map, you can both create new nodes with
  53. nodeCreate(), and make new connections between existing nodes with
  54. connectionCreate():
  55. .CS
  56. nodeCreate(<nodeId>);
  57. connectionCreate(<nodeId1>, <nodeId2>);
  58. .CE
  59. (6) To kill everything and end the demo:
  60. .CS
  61. graphStop();
  62. .CE
  63. INTERNAL
  64. The following is the thread of execution of this test program.
  65. The ":" trace stands for a given net (a set of node creation and connection 
  66. creation). The "|" trace stands for modification of that net. New nodes
  67. can be appended to the net, but only new connections or color changes
  68. trigger the task resumes. The "#" tag stands for end of task.
  69.        Stability   Node       Connection   Graph     Color    Graph       Graph
  70. Node   Detection   Creation   Creation    Display   Change   Init        Stop
  71. Task   Task    Task       Task   Task     Task     Task        Task
  72. ====   =========   ========   =========   =======   ======   =====       =====
  73.                       :          :   |                |         |          |
  74.                       :          :   |                |         |          |
  75.                       :          :   |                |   spawn stability  |
  76.                       :          :   |                |       /            |
  77.                       :          :   |                |      /             |
  78.            <------------------------------------------------/              |
  79.            |          :          :   |                |         |          |
  80.            |      spawn node     :   |                |         #          |
  81.            |          /          :   |                |                    |
  82.            |         /           :   |                |                    |
  83.   <--------|--------/            :   |                |                    |
  84.            |         #           :   |                |                    |
  85.            |                     #   |                |                    |
  86.       [stability]                    |                |                    |
  87.                                     |                |                    |
  88.                                     |                |                    |
  89.               ----------------------------->         |                    |
  90.    taskSuspend Node Tasks            |      |         |                    |
  91.           /                          |      #         |                    |
  92.          /                           |                |                    |
  93.   <-----/                            |                |                    |
  94.     taskSuspend itself               |                |                    |
  95.                                      |                |                    |
  96.                                      |                |                    |
  97.                             taskResume Node Tasks     |                    |
  98.                                      /                |                    |
  99.                                     /                 |                    |
  100.   <--------------------------------/          taskResume Node Tasks        |
  101.   |                         taskResume Stability      #                    |
  102.   |                                  /                                     |
  103.   |                                 /                                      |
  104.   |        <-----------------------/                                       |
  105.   |        |                        |                                      |
  106.   |        |                        #                                      |
  107.   |        |                                                               |
  108.   |        |                                       taskdelete Node + stability
  109.   |        |                                                               /
  110.   |        |                                                              /
  111.   <--------<-------------------------------------------------------------/
  112.   #        #                                                               |
  113.                                                                            #
  114. INCLUDE FILES:
  115. */
  116. /* includes */
  117. #include "vxWorks.h"
  118. #include "taskLib.h"
  119. #include "msgQLib.h"
  120. #include "stdarg.h"
  121. #include "stdio.h"
  122. #include "tickLib.h"
  123. #include "kernelLib.h"
  124. /* defines */
  125. #define GRAPHMAXNODE 100 /* graph max node number */
  126. #define NODEMAXCONNEX 10 /* node max connection number */
  127. #define MAX_MSG 50 /* max messg number in queue */
  128. #define MSG_SIZE sizeof (NODE_ATTRIB) /* size of message */
  129. #define COLORMAX 6 /* maximum number of color */
  130. #define OUTDEGREEMAX 5 /* node max out degree */
  131. #define OUTDEGREEINIT (OUTDEGREEMAX + 1)
  132. #define STEP_TICKS 6 /* inter node processing  ticks count */
  133. /* typedefs */
  134. typedef struct /* IDS */
  135.     {
  136.     int tid; /* task id */
  137.     char nid; /* node id */
  138.     } IDS; /* task/node id */
  139. typedef struct /* NODE_ATTRIB */
  140.     {
  141.     char color; /* node color */
  142.     int Xvalue; /* node Xvalue */
  143.     } NODE_ATTRIB; /* node attributes */
  144. typedef struct /* CONNECT_INFO */
  145.     {
  146.     char dir; /* direction: +=to connected -=from connected */
  147.     IDS tnid; /* connected node tid & nid */
  148.     NODE_ATTRIB att; /* connected node attributes */
  149.     MSG_Q_ID wMQId; /* write (toNeighbor) mesg queue id */
  150.     MSG_Q_ID rMQId; /* read  (toNeighbor) mesg queue id */
  151.     } CONNECT_INFO; /* connected node info */
  152. typedef struct /* GNODE */
  153.     {
  154.     char stable; /* color stability flag */
  155.     char rev; /* DAG reversing flag */
  156.     IDS tnid; /* node tid & nid */
  157.     NODE_ATTRIB att; /* node col & Xval */
  158.     int pc; /* node Prog Counter */
  159.     int oD; /* node outDegree */
  160.     int cNum; /* node connections # */
  161.     CONNECT_INFO cArray[NODEMAXCONNEX]; /* node connections array */
  162.     } GNODE; /* global node info */
  163. typedef struct /* DATA_BASE */
  164.     {
  165.     char nNum; /* graph node # */
  166.     GNODE nArray[GRAPHMAXNODE]; /* graph node array */
  167.     } DATA_BASE; /* global graph info */
  168. /* globals */
  169. DATA_BASE dB; /* global data base of nodes */
  170. int graphControlId; /* graphControl task Id */
  171. SEM_ID nodeSyncSem; /* node sync semaphore */
  172. SEM_ID graphSem; /* graph mutex semaphore */
  173. /* locals */
  174. /* forward declarations */
  175. int  nodeChecks (int nodeId);
  176. int  nodeCreate (int nodeId);
  177. void  nodeInit (int nodeId, GNODE * pNode);
  178. LOCAL void nodeJob(int nodeId, GNODE * pNode);
  179. int  graphColoring (GNODE * pNode);
  180. void  graphControl (void);
  181. void  graphDisp (int mode);
  182. void graphInit (void);
  183. void  graphStop (void);
  184. int  colorChange (int nodeId, int mode, int newColor);
  185. void  colTest (int opCode);
  186. int  connectionCreate (int nid1, int nid2);
  187. BOOL  consistencyTest (void);
  188. /*******************************************************************************
  189. *
  190. * neighborTalk - talking with the pc ranked neihgbor
  191. *
  192. * Note about the inter nodes communication phase:
  193. * Trial: read a neighbor at a time for the color only
  194. * actually, all processNodes write their color to all their neighbors
  195. * and each process node read all its links to empty them
  196. * (avoiding pipes to get full), but only one value is used.
  197. *
  198. */
  199. void neighborTalk 
  200.     (
  201.     GNODE * pNode /* current node */
  202.     )
  203.     {
  204.     NODE_ATTRIB att; /* attributes */
  205.     int ix; /* connected node index */
  206.     int retVal; /* msgQ operation result */
  207.     att = pNode->att;
  208.     /* writing connected nodes */
  209.     for (ix=0; ix< pNode->cNum; ix++)
  210. retVal = msgQSend (pNode->cArray[ix].wMQId, (char *) &att, MSG_SIZE,
  211.    WAIT_FOREVER, MSG_PRI_NORMAL);
  212.     /* reading connected nodes, especially rank=pc one */
  213.     for (ix=0; ix< pNode->cNum; ix++)
  214. {
  215. retVal = msgQReceive (pNode->cArray[ix].rMQId, (char *) &att,
  216.       MSG_SIZE, NO_WAIT);
  217. if (ix == pNode->pc)
  218.     pNode->cArray[ix].att =  att;
  219. }
  220.     }
  221. /*******************************************************************************
  222. *
  223. * graphColoring - DAG & Coloring processing
  224. *
  225. *
  226. */
  227. int graphColoring 
  228.     (
  229.     GNODE * pNode /* current node */
  230.     )
  231.     {
  232.     int ix; /* index */
  233.     int outDegree; /* outdegree of this node */
  234.     int colConf; /* if color conflict */
  235.     int col[COLORMAX]; /* color check array */
  236.     long XvalueMax; /* max Xvalue of node */
  237. #if 0
  238.     /* not used */
  239.     NODE_ATTRIB att; /* attributes */
  240. #endif
  241.     if (pNode->pc < pNode->cNum) /* connected neighbors scaning uncompleted */
  242.         {
  243. /* talking with pc ranked neighbor */
  244. neighborTalk (pNode);
  245. /* program counter incrementation */
  246. pNode->pc++;
  247.         }
  248.     else /* connected neighbors scaning completed */
  249.         {
  250. /* DAG conversion: computes links directions and outDegree */
  251. XvalueMax = 0;
  252.         outDegree = 0;
  253.      for (ix=0; ix < pNode->cNum; ix++)
  254.     {
  255.     if ( (pNode->att.Xvalue < pNode->cArray[ix].att.Xvalue ) || 
  256.  ( (pNode->att.Xvalue == pNode->cArray[ix].att.Xvalue) &&
  257.    (pNode->tnid.nid < pNode->cArray[ix].tnid.nid) ) )
  258. {
  259. pNode->cArray[ix].dir = '+';
  260. outDegree++;
  261. if (pNode->cArray[ix].att.Xvalue > XvalueMax)
  262.     XvalueMax = pNode->cArray[ix].att.Xvalue;
  263.         }
  264.     else
  265. {
  266. pNode->cArray[ix].dir = '-';
  267.         }
  268.     }
  269. pNode->oD = outDegree;
  270.         if (outDegree > OUTDEGREEMAX)
  271.     {
  272.     /* DAG conversion: reversing current node */
  273.     printf("reversing %d: Xvalue from %d to Xvalue = %ld.n",
  274.    pNode->tnid.nid, pNode->att.Xvalue, XvalueMax + 1);
  275.             pNode->att.Xvalue = XvalueMax + 1;
  276.     pNode->rev++;
  277.             }
  278. else /* outDegree <= OUTDEGREEMAX : this enables coloring algo */
  279.     {
  280.     /* COL : detecting color conflict and 'n' tagging used color */
  281.             colConf = 0;
  282.          for (ix=0; ix<6; ix++)
  283. col[ix] = 'y';
  284.          for (ix=0; ix < pNode->cNum; ix++)
  285. {
  286.         if (pNode->cArray[ix].dir == '+')
  287.     {
  288.             if (pNode->att.color == pNode->cArray[ix].att.color)
  289. colConf = 1;
  290.             col[(unsigned int)(pNode->cArray[ix].att.color)] = 'n';
  291.             }
  292.         }
  293.     /* COL: update color in case of coloring conflict */
  294.     if ( colConf == 1 )
  295. {
  296. ix=0; /* looks for the first free color */
  297. while( ix<6 && col[ix]=='n')
  298.     ix++;
  299. if (ix==6)
  300.     {
  301.     printf("End of node %d: col error.n", pNode->tnid.nid);
  302.     exit(2);
  303.     }
  304. else
  305.     {
  306.     printf("Node %d: color update %d --> %dn",
  307. pNode->tnid.nid, pNode->att.color, ix);
  308.     pNode->att.color = ix;
  309.     }
  310. pNode->stable = 0;
  311.         }
  312.     else
  313. {
  314. pNode->stable = 1;
  315.         }
  316.     }
  317.     /* reset program counter */
  318. pNode->pc  = 0;
  319.         }
  320.     return 0;
  321.     }
  322. /*******************************************************************************
  323. *
  324. * consistencyTest - tests whether arcs are well oriented throughout the graph
  325. *
  326. * RETURNS: TRUE if graph is consistent, FALSE otherwise
  327. */
  328. BOOL consistencyTest (void)
  329.     {
  330.     int i; /* node index */
  331.     int j; /* connected node index */
  332.     int k; /* node index */
  333.     int l; /* connected node index */
  334.     char dir1; /* link direction */
  335.     char dir2; /* link direction */
  336.     for(i=0; i<dB.nNum; i++)
  337. {
  338. for(j=0; j<dB.nArray[i].cNum; j++)
  339.     {
  340.     if (dB.nArray[i].att.color == dB.nArray[i].cArray[j].att.color)
  341. {
  342. printf("(i,j)=(%d,%d) direct color conflict.n", i, j);
  343. return FALSE;
  344.              }
  345.          if ( (k = nodeChecks (dB.nArray[i].cArray[j].tnid.nid)) == -1 )
  346. {
  347. printf("Bad link definition.n");
  348. return FALSE;
  349. }
  350.     /* is that node at rank k has correct connected info */
  351.          l = 0;
  352.          while ( l<dB.nArray[k].cNum && 
  353.     dB.nArray[k].cArray[l].tnid.nid != dB.nArray[i].tnid.nid )
  354. l++;
  355.          if (l == dB.nNum)
  356. {
  357. printf("Symetric link violation.n");
  358. return FALSE;
  359.              }
  360.     /* is that node at rank k has correct color */
  361.     if ( dB.nArray[i].cArray[j].att.color != dB.nArray[k].att.color )
  362. {
  363. printf("(i,j,k)=(%d,%d,%d) connection color inconsistency.n", i, j, k);
  364. return FALSE;
  365.              }
  366.     dir1 = dB.nArray[i].cArray[j].dir;
  367.     dir2 = dB.nArray[k].cArray[l].dir;
  368.     if ( (dir1 != '+' && dir1 != '-') || (dir2 != '+' && dir2 != '-')
  369.  || (dir1==dir2) )
  370. {
  371. printf("Asymetric direction inconsistency.n");
  372. return FALSE;
  373.         }
  374.     }
  375.         }
  376.     return TRUE;
  377.     }
  378. /*******************************************************************************
  379. *
  380. * colorChange - randomly change a node color
  381. *
  382. * note: database is a critical resource that needs a mutex semaphore
  383. */
  384. int colorChange
  385.     (
  386.     int nodeId, /* node id */
  387.     int mode, /* colorChange mode: 1 = random, 2 = specified color */
  388.     int newColor /* specified color of the colorChange mode # 2 */
  389.     )
  390.     {
  391.     int rank; /* node rank in the database */
  392.     char color; /* temporary color */
  393.     /* checks if that node id is already in use in the graph */
  394.     if ( (rank = nodeChecks (nodeId)) == -1 )
  395. {
  396. printf("No such node id %d in current graph.n", nodeId);
  397. return -1;
  398. }
  399.     switch (mode)
  400. {
  401. case 1: /* randomly picks out a color among 6 values */
  402.          srand (tickGet ());
  403.          color = dB.nArray[rank].att.color;
  404.          while ( color == dB.nArray[rank].att.color)
  405.         color = rand()%6;
  406.     break;
  407. case 2:
  408.     color = newColor;
  409.     break;
  410. default: 
  411.     printf("Unknown colorChange mode.n");
  412.     exit(0);
  413. }
  414.     printf("Node %d: color change %d --> %d.n", nodeId,
  415.    dB.nArray[rank].att.color, color);
  416.     /* access the dataBase critical resource */
  417.     semTake (graphSem, -1);
  418.     dB.nArray[rank].att.color = color;
  419.     dB.nArray[rank].stable    = 0;
  420.     /* give back the dataBase critical resource */
  421.     semGive (graphSem);
  422.     /* resume the graphControl task */
  423.     taskResume (graphControlId);
  424.     return 0;
  425. }
  426. /*******************************************************************************
  427. *
  428. *  graphDisp - display current graph state
  429. *
  430. * note: database access should be frozzen during the display
  431. *
  432. */
  433. void graphDisp
  434.     (
  435.     int mode /* display mode 2 = full !2 = regular */
  436.     )
  437.     {
  438.     int i, j;
  439.     printf("******n* dataBase graph info:n*n");
  440.     printf("nid color Xvalue sb oD Rev cNum connected nodesn");
  441.     for(i=0; i<dB.nNum; i++)
  442. {
  443. printf("%3d %5d %6d %2d %2d %3d %4d", 
  444.     dB.nArray[i].tnid.nid,
  445.     dB.nArray[i].att.color,
  446.     dB.nArray[i].att.Xvalue,
  447.     dB.nArray[i].stable,
  448.     dB.nArray[i].oD,
  449.     dB.nArray[i].rev,
  450.     dB.nArray[i].cNum);
  451. if (mode==2) /* full display */
  452.     {
  453.     for(j=0; j<dB.nArray[i].cNum; j++)
  454. printf(" * %2d%c %6d %d", dB.nArray[i].cArray[j].tnid.nid,
  455.      dB.nArray[i].cArray[j].dir, dB.nArray[i].cArray[j].att.Xvalue,
  456.   dB.nArray[i].cArray[j].att.color);
  457.     }
  458. printf("n");
  459.         }
  460.     }
  461. /*******************************************************************************
  462. *
  463. * graphInit - coloring graph initialization
  464. *
  465. */
  466. void graphInit (void)
  467.     {
  468.     /* set initial node number to 0 */
  469.     dB.nNum = 0;
  470.     /*
  471.      * enabling round robin: necessary to give each node of the
  472.      * graph (which have all the same priority) some CPU access
  473.      */
  474.     kernelTimeSlice(2);
  475.     /* spawn graphControl with low priority (199) to let tasks spawned from
  476.      * the shell (100) able to run, but with higher priority than node's tasks
  477.      * (200) to provides fast display 
  478.      */
  479.     graphControlId = taskSpawn ("tContrNet", 199, VX_SUPERVISOR_MODE,
  480. 10000, (FUNCPTR) graphControl, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  481.     }
  482. /*******************************************************************************
  483. *
  484. * graphControl - graph supervisor task
  485. *
  486. */
  487. void graphControl (void)
  488.     {
  489.     int ix; /* node index */
  490.     /* sync binary semaphore to avoid nodes keep running */
  491.     nodeSyncSem = semBCreate (0, SEM_EMPTY);
  492.     /* binary semaphore to provide graph mutex protection */
  493.     graphSem = semBCreate (0, SEM_FULL);
  494.     FOREVER
  495. {
  496. /* access the dataBase critical resource */
  497. semTake (graphSem, -1);
  498. /* unblocks all the nodes in an atomic way */
  499. semFlush (nodeSyncSem);
  500. /* check stability */
  501. if (dB.nNum > 0)
  502.     {
  503.     ix=0;
  504.     while (ix<dB.nNum && dB.nArray[ix].stable == 1)
  505. ix++;
  506.     if (ix == dB.nNum) /* nodes are stable */
  507. {
  508. if (consistencyTest ()) /* dataBase is stable */
  509.     {
  510.     graphDisp (0);
  511.     semGive (graphSem);
  512.                  taskSuspend (0); /* suspend itself */
  513.     semTake (graphSem, -1);
  514.     }
  515. }
  516.     }
  517. /* hereunder delay should be enough for one step of coloring */
  518. taskDelay (STEP_TICKS);
  519. /* give back the dataBase access */
  520. semGive (graphSem);
  521. }
  522.     }
  523. /*******************************************************************************
  524. *
  525. * nodeCreate - node creation
  526. *
  527. */
  528. int nodeCreate
  529.     (
  530.     int nodeId
  531.     )
  532.     {
  533.     char  name[8];
  534.     GNODE * pNode;
  535.     /* checks if that node id is already in use in the graph */
  536.     if ( nodeChecks (nodeId) != -1 )
  537. {
  538. printf("Node id %d already used in current graph.n", nodeId);
  539. return -1;
  540. }
  541.     /* check if the authorized maximum number of node is reached */
  542.     if (dB.nNum == GRAPHMAXNODE-1)
  543. {
  544. printf("GRAPHMAXNODE reached!n");
  545. return -1;
  546. }
  547.     sprintf(name, "tNode%d", nodeId);
  548.     pNode = &(dB.nArray[(unsigned int)dB.nNum]);
  549.     dB.nNum++;
  550.     /* spawn nodeJob with lower priority (200) than the default (100) */
  551.     dB.nArray[dB.nNum-1].tnid.tid = 
  552. taskSpawn (name, 200, VX_SUPERVISOR_MODE, 10000, (FUNCPTR) nodeJob ,
  553.    nodeId, (int) pNode, 0, 0, 0, 0, 0, 0, 0, 0);
  554.     return 0;
  555. }
  556. /*******************************************************************************
  557. *
  558. * nodeChecks - checks about a given node
  559. *
  560. * tests if a given node id is declared in the current database and if the
  561. * connected node number (cNum) is under the limit
  562. *
  563. * RETURNS: -1 if bad node or bad cNum, rank in the database otherwise
  564. *
  565. */
  566. int nodeChecks
  567.     (
  568.     int  nodeId /* node id */
  569.     )
  570.     {
  571.     int ix; /* index */
  572.     /* tests if the node exists */
  573.     ix = 0;
  574.     while (ix<dB.nNum && dB.nArray[ix].tnid.nid != nodeId)
  575. ix++;
  576.     if (ix == dB.nNum)
  577. return -1;
  578.     /* tests if the connected node number is under the limit */
  579.     if (dB.nArray[ix].cNum == NODEMAXCONNEX)
  580. return -1;
  581.     /* return the rank in the database */
  582.     return ix;
  583.     }
  584. /*******************************************************************************
  585. *
  586. * connectionCreate - establish a connection between two nodes 
  587. *
  588. * the database is a critical resource that needs a mutex semaphore
  589. *
  590. */
  591. int connectionCreate
  592.     (
  593.     int nid1, 
  594.     int nid2
  595.     )
  596.     {
  597.     int cNum1;
  598.     int cNum2;
  599.     int rank1;
  600.     int rank2;
  601.     MSG_Q_ID mqId;
  602.     /* dataBase access request */
  603.     semTake (graphSem, -1);
  604.     /* check nodes id */
  605.     if ( (rank1 = nodeChecks (nid1)) == -1 )
  606. {
  607. printf("No such node Id or NODEMAXCONNEX reached!n");
  608. exit(2);
  609. }
  610.     cNum1 = dB.nArray[rank1].cNum;
  611.     if ( (rank2 = nodeChecks (nid2)) == -1 )
  612. {
  613. printf("No such node Id or NODEMAXCONNEX reached!n");
  614. exit(2);
  615. }
  616.     cNum2 = dB.nArray[rank2].cNum;
  617.     dB.nArray[rank1].cArray[cNum1].tnid = dB.nArray[rank2].tnid;
  618.     dB.nArray[rank1].cArray[cNum1].dir = '0'; /* init with no direction */
  619.     dB.nArray[rank1].cNum++;
  620.     dB.nArray[rank2].cArray[cNum2].tnid = dB.nArray[rank1].tnid;
  621.     dB.nArray[rank2].cArray[cNum2].dir = '0'; /* init with no direction */
  622.     dB.nArray[rank2].cNum++;
  623.     /* create two Message Queues for node1 <-> node2 full duplex */
  624.     if ( (mqId = msgQCreate(MAX_MSG, MSG_SIZE, MSG_Q_PRIORITY)) == NULL )
  625. return (ERROR);
  626.     dB.nArray[rank1].cArray[cNum1].wMQId = mqId;
  627.     dB.nArray[rank2].cArray[cNum2].rMQId = mqId;
  628.     if ( (mqId = msgQCreate(MAX_MSG, MSG_SIZE, MSG_Q_PRIORITY)) == NULL )
  629. return (ERROR);
  630.     dB.nArray[rank1].cArray[cNum1].rMQId = mqId;
  631.     dB.nArray[rank2].cArray[cNum2].wMQId = mqId;
  632.     /*printf("Link %d<->%d established.n", nid1, nid2);*/
  633.     /* free dataBase access */
  634.     semGive (graphSem);
  635.     /* resume the graphControl task (nop if graphControl already alive) */
  636.     taskResume (graphControlId);
  637.     return 0;
  638. }
  639. /*******************************************************************************
  640. *
  641. * nodeJob - task performed by each nodes in the graph
  642. *
  643. * More detailed description
  644. *
  645. */
  646. LOCAL void nodeJob 
  647.     (
  648.     int nodeId, /* id of the node */
  649.     GNODE * pNode /* node processed by this task */
  650.     )
  651.     {
  652.     /* node initialization */
  653.     nodeInit(nodeId, pNode);
  654.     /*printf("Node %d registered with random color=%d and random Xvlue = %dn",
  655.     nodeId, pNode->att.color, pNode->att.Xvalue);*/
  656.     FOREVER
  657. {
  658. /*
  659.  * each node block on the same semaphore (this avoid using here a
  660.  * taskDelay which leads, when used with many tasks, to sync problems)
  661.  */
  662. semTake (nodeSyncSem, -1);
  663. if (pNode->cNum > 0)
  664.     graphColoring (pNode);
  665. }
  666.     }
  667.     
  668. /*******************************************************************************
  669. *
  670. * nodeInit - node initialization 
  671. *
  672. * More detailed description
  673. *
  674. */
  675. void nodeInit
  676.     (
  677.     int nodeId, /* id of the node */
  678.     GNODE * pNode /* node processed by this task */
  679.     )
  680.     {
  681.     /* random number generator init */
  682.     srand (tickGet () + taskIdSelf ());
  683.     /* node initialization */
  684.     pNode->tnid.tid = taskIdSelf ();
  685.     pNode->tnid.nid = nodeId;
  686.     pNode->cNum  = 0;
  687.     pNode->rev  = 0;
  688.     pNode->pc  = 0;
  689.     pNode->stable  = -1;
  690.     pNode->oD  = OUTDEGREEINIT;
  691.     pNode->att.color = rand()%6;
  692.     pNode->att.Xvalue = rand();
  693.     }
  694. /*******************************************************************************
  695. *
  696. * graphStop - collective Suicide
  697. *
  698. * kills task node's task, control task, mesgQs & semaphores
  699. *
  700. */
  701. void graphStop (void)
  702.     {
  703.     int ix; /* node index */
  704.     int jx; /* connected node index */
  705.     semDelete(graphSem);
  706.     semDelete(nodeSyncSem);
  707.     taskDelete(graphControlId);
  708.     for(ix=0; ix< dB.nNum; ix++)
  709. taskDelete(dB.nArray[ix].tnid.tid);
  710.     for(ix=0; ix< dB.nNum; ix++)
  711.         {
  712. for(jx=0; jx< dB.nArray[ix].cNum; jx++)
  713.     {
  714.     msgQDelete(dB.nArray[ix].cArray[jx].rMQId);
  715.     msgQDelete(dB.nArray[ix].cArray[jx].wMQId);
  716.     }
  717.         }
  718.     printf("Graph coloring is finished.n");
  719.     }
  720. /*******************************************************************************
  721. *
  722. * connectFullNode - performs full connections for a given node
  723. *
  724. */
  725. void connectFullNode
  726.     (
  727.     int nodId, /* current node id */
  728.     int nb_arg, /* number of argument = connection # */
  729.     ... /* ellipse */
  730.     )
  731.     {
  732.     int ix; /* index */
  733.     va_list p_list; /* ellipse list */
  734.     va_start(p_list, nb_arg);
  735.     for (ix=0; ix<nb_arg; ix++)
  736. connectionCreate(nodId, va_arg(p_list, int));
  737.     }
  738. /*******************************************************************************
  739. *
  740. * entry point for colTest 
  741. *
  742. */
  743. void colTest 
  744.     (
  745.     int opCode
  746.     )
  747.     {
  748.     int ix; /* index */
  749.     if (opCode == 1)
  750. for(ix=1; ix<10; ix++)
  751.     nodeCreate(ix);
  752.     if (opCode == 2) {
  753. connectFullNode(1, 7, 2, 4, 5, 6, 7, 8, 9);
  754. connectionCreate(2, 6);
  755. connectFullNode(3, 3, 4, 5, 8);
  756. connectFullNode(4, 2, 5, 8);
  757. connectionCreate(5, 8);
  758. connectFullNode(6, 2, 7, 8);
  759. connectFullNode(7, 2, 8, 9);
  760. connectionCreate(8, 9);
  761.     }
  762.     if (opCode == 3)
  763. for(ix=1; ix<10; ix++)
  764.     nodeCreate(ix);
  765.     if (opCode == 4) {
  766. connectionCreate(1, 9);
  767. connectionCreate(9, 2);
  768. for(ix=2; ix<9; ix++) {
  769.     connectionCreate(1, ix);
  770.     connectionCreate(ix, ix+1);
  771. }
  772.     }
  773.     if (opCode == 5) { /* French counties */
  774. for(ix=1; ix<96; ix++)
  775.     nodeCreate(ix);
  776.     }
  777.     if (opCode == 6)
  778.         /* connections between counties of the french territory */
  779.     
  780. connectFullNode(1, 6, 38, 39, 69, 71, 73, 74); /* Ain */
  781. connectFullNode(2, 6, 8, 51, 59, 60, 62, 77); /* Aisne */
  782. connectFullNode(3, 6, 18, 23, 42, 58, 63, 71); /* Allier */
  783. connectFullNode(4, 6, 5, 6, 13, 26, 83, 84); /* Alpes Haute Provence */
  784. connectFullNode(5, 4, 26, 38, 73, 84); /* Hautes Alpes */
  785. connectionCreate(6, 83); /* Alpes maritimes */
  786. connectFullNode(7, 5, 26, 30, 42, 43, 48); /* Ardeche */
  787. connectFullNode(8, 2, 51, 55); /* Ardennes */
  788. connectFullNode(9, 3, 11, 31, 66); /* Ariege */
  789. connectFullNode(10, 5, 21, 51, 52, 77, 89); /* Aube */
  790. connectFullNode(11, 4, 34, 66, 81, 82); /* Aude */
  791. connectFullNode(12, 7, 15, 30, 34, 46, 48, 81, 82); /* Aveyron */
  792. connectFullNode(13, 4, 20, 30, 83, 84); /* Bouches du Rhone */
  793. connectFullNode(14, 4, 27, 50, 61, 76); /* Calvados */
  794. connectFullNode(15, 5, 19, 43, 46, 48, 63); /* Cantal */
  795. connectFullNode(16, 6, 17, 24, 33, 79, 86, 87); /* Charente */
  796. connectFullNode(17, 3, 33, 79, 85); /* Charente maritime */
  797. connectFullNode(18, 5, 23, 36, 41, 45, 58); /* Cher */
  798. connectFullNode(19, 6, 23, 24, 46, 63, 87); /* Correze */
  799.         /* Corse 20: no connection  */
  800. connectFullNode(21, 6, 39, 52, 58, 70, 71, 89); /* Cote d'or */
  801. connectFullNode(22, 3, 29, 35, 56); /* Cote d'armor */
  802. connectFullNode(23, 3, 36, 63, 87); /* Creuse */
  803. connectFullNode(24, 4, 33, 46, 47, 87); /* Dordogne */
  804. connectFullNode(25, 3, 39, 70, 90); /* Doubs */
  805. connectFullNode(26, 3, 30, 38, 84); /* Drome */
  806. connectFullNode(27, 7, 41, 45, 60, 61, 76, 78, 95); /* Eure */
  807. connectFullNode(28, 5, 41, 45, 61, 78, 91); /* Eure  et loir */
  808. connectionCreate(29, 56); /* Finistere */
  809. connectFullNode(30, 3, 34, 48, 84); /* Gard */
  810. connectFullNode(31, 4, 32, 65, 81, 82); /* Haute Garonne */
  811. connectFullNode(32, 5, 40, 47, 64, 65, 82); /* Gers */
  812. connectFullNode(33, 2, 40, 47); /* Gironde */
  813. connectionCreate(34, 81); /* Herault */
  814. connectFullNode(35, 4, 44, 50, 53, 56); /* Ile et vilaine */
  815. connectFullNode(36, 4, 37, 41, 86, 87); /* Indre */
  816. connectFullNode(37, 4, 41, 49, 72, 86); /* Indre et Loire */
  817. connectFullNode(38, 2, 69, 73); /* Isere */
  818. connectFullNode(39, 2, 70, 71); /* Jura */
  819. connectFullNode(40, 2, 47, 64); /* Landes */
  820. connectFullNode(41, 2, 45, 72); /* Loire et Cher */
  821. connectFullNode(42, 4, 43, 63, 69, 71); /* Loire */
  822. connectFullNode(43, 2, 48, 63); /* Haute Loire */
  823. connectFullNode(44, 3, 49, 56, 85); /* Loire Atlantique */
  824. connectFullNode(45, 4, 58, 77, 89, 91); /* Loiret */
  825. connectFullNode(46,  2, 47, 82); /* Lot */
  826. connectionCreate(47, 82); /* Lot et Garonne */
  827.         /* Lozere 48 : no connection  */
  828. connectFullNode(49, 5, 53, 72, 79, 85, 86); /* Maine et Loire */
  829. connectionCreate(50, 53); /* Manche  */
  830. connectFullNode(51, 3, 52, 55, 77); /* Marne */
  831. connectFullNode(52, 3, 55, 70, 88); /* Haute Marne */
  832. connectFullNode(53, 2, 61, 72); /* Mayenne */
  833. connectFullNode(54, 4, 55, 57, 67, 88); /* Meurthe et Moselle */
  834. connectFullNode(55, 2, 57, 88); /* Meuse */
  835.         /* Morbihan   56  */
  836. connectionCreate(57, 67); /* Moselle */
  837. connectionCreate(58, 71); /* Nievre */
  838. connectFullNode(59, 2, 62, 80); /* Nord */
  839. connectFullNode(60, 4, 76, 77, 80, 95); /* Oise */
  840. connectionCreate(61, 72); /* Orne */
  841. connectionCreate(62, 80); /* Pas de calais */
  842.         /* Puy de Dome   63   */
  843. connectionCreate(64, 65); /* Pyrennees Atlantiques */
  844.         /* Hautes Pyrennees  65 */
  845.         /* Pyrennees Orientales 66 */
  846. connectFullNode(67, 2, 68, 88); /* Bas Rhin */
  847. connectFullNode(68, 2, 88, 90); /* Haut Rhin */
  848. connectionCreate(69, 71); /* Rhone */
  849. connectFullNode(70, 2, 88, 90); /* Haute Saone */
  850.         /* Saone et Loire 71 */
  851.         /* Sarthe 72*/
  852. connectionCreate(73, 74); /* Savoie */
  853.         /* Haute Savoie 74 */
  854. connectFullNode(75, 3, 92, 93, 94); /* Paris */
  855. connectionCreate(76, 80); /* Seine Maritime */
  856. connectFullNode(77, 4, 89, 91, 93, 94); /* Seine et Marne */
  857. connectFullNode(78, 3, 91, 92, 95); /* Yvelines */
  858. connectFullNode(79, 2, 85, 86); /* Deux Sevres */
  859.         /* Somme  80 */
  860. connectionCreate(81, 82); /* Tarn */
  861.         /* Tarn  et garonne 82 */
  862.         /* Var 83 */
  863.         /* Vaucluse 84 */
  864.         /* Vendee  85 */
  865. connectionCreate(86, 87); /* Vienne */
  866.         /* Haute Vienne 87 */
  867.         /* Vosges  88 */
  868.         /* Yonne  89 */
  869.         /* Territoire de Belfort  90 */
  870. connectFullNode(91, 2, 92, 94); /* Essonne */
  871. connectFullNode(92, 3, 93, 94, 95); /* Hauts de Seine */
  872. connectFullNode(93,  2, 94, 95); /* Seine St Denis */
  873.         /* Val de Seine 94 */
  874.         /* Val d'Oise 95 */
  875.         }
  876.     }