A2.Enet.Mod 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. MODULE Enet; (** AUTHOR ""; PURPOSE ""; *)
  2. IMPORT
  3. EnetBase, EnetTiming, EnetArp, EnetIcmp, EnetUdp, Objects, Locks, Kernel, Machine, Interfaces := EnetInterfaces, Trace;
  4. CONST
  5. MaxNumInterfaces* = 2; (** maximal supported number of interfaces *)
  6. MaxArpCacheSize* = 256;
  7. UseSpinLocks* = TRUE; (** TRUE for forcing the use of spin locks *)
  8. TYPE
  9. Int32 = EnetBase.Int32;
  10. Int16 = EnetBase.Int16;
  11. Int = EnetBase.Int;
  12. Interface* = OBJECT(EnetBase.Interface)
  13. VAR
  14. res: Int;
  15. alive: BOOLEAN;
  16. exited: BOOLEAN;
  17. waiting, waitingReq: BOOLEAN;
  18. lockDevRxFlag, lockDevTxFlag: BOOLEAN;
  19. lockDevRxPacketPoolFlag, lockDevTxPacketPoolFlag: BOOLEAN;
  20. lockTasksFlag: BOOLEAN;
  21. lockIpv4AddrCacheFlag, lockIpv6AddrCacheFlag: BOOLEAN;
  22. lockDevRx, lockDevTx: Locks.Lock;
  23. lockDevRxPacketPool, lockDevTxPacketPool: Locks.Lock;
  24. lockTasks: Locks.Lock;
  25. lockIpv4AddrCache, lockIpv6AddrCache: Locks.RWLock;
  26. PROCEDURE &InitInterface*(
  27. dev: EnetBase.LinkDevice;
  28. VAR res: Int
  29. );
  30. BEGIN
  31. IF ~Interfaces.InitInterface(SELF,dev,res) THEN RETURN; END;
  32. IF UseSpinLocks THEN SetupSpinLocks(FALSE); ELSE SetupLocks(FALSE); END;
  33. (*
  34. setup support of basic protocols
  35. *)
  36. EnetArp.Install(SELF);
  37. EnetIcmp.Install(SELF);
  38. EnetUdp.Install(SELF);
  39. IF UseSpinLocks THEN SetupSpinLocks(TRUE); ELSE SetupLocks(TRUE); END;
  40. (*
  41. setup interface-specific methods
  42. *)
  43. start := Start;
  44. stop := Stop;
  45. reset := Reset;
  46. finalize := Finalize;
  47. IF res = 0 THEN
  48. alive := TRUE;
  49. waitingReq := TRUE;
  50. waiting := TRUE;
  51. exited := FALSE;
  52. ELSE
  53. alive := FALSE;
  54. END;
  55. END InitInterface;
  56. PROCEDURE SetupLocks(ipAddrCacheOnly: BOOLEAN);
  57. BEGIN
  58. IF ~ipAddrCacheOnly THEN
  59. NEW(lockDevRx);
  60. NEW(lockDevTx);
  61. NEW(lockDevRxPacketPool);
  62. NEW(lockDevTxPacketPool);
  63. NEW(lockTasks);
  64. (*
  65. setup link device-specific locks
  66. *)
  67. dev.acquireRx := lockDevRx.Acquire;
  68. dev.releaseRx := lockDevRx.Release;
  69. dev.acquireTx := lockDevTx.Acquire;
  70. dev.releaseTx := lockDevTx.Release;
  71. dev.rxPacketPool.acquire := lockDevRxPacketPool.Acquire;
  72. dev.rxPacketPool.release := lockDevRxPacketPool.Release;
  73. dev.txPacketPool.acquire := lockDevTxPacketPool.Acquire;
  74. dev.txPacketPool.release := lockDevTxPacketPool.Release;
  75. (*
  76. setup locks for interface-specific tasks management
  77. *)
  78. acquireTasks := lockTasks.Acquire;
  79. releaseTasks := lockTasks.Release;
  80. ELSE
  81. NEW(lockIpv4AddrCache);
  82. NEW(lockIpv6AddrCache);
  83. (*
  84. setup locks for IP address resolution caches
  85. *)
  86. IF ipv4AddrCache # NIL THEN
  87. ipv4AddrCache.acquireWrite := lockIpv4AddrCache.AcquireWrite;
  88. ipv4AddrCache.releaseWrite := lockIpv4AddrCache.ReleaseWrite;
  89. ipv4AddrCache.acquireRead := lockIpv4AddrCache.AcquireRead;
  90. ipv4AddrCache.releaseRead := lockIpv4AddrCache.ReleaseRead;
  91. END;
  92. IF ipv6AddrCache # NIL THEN
  93. ipv6AddrCache.acquireWrite := lockIpv6AddrCache.AcquireWrite;
  94. ipv6AddrCache.releaseWrite := lockIpv6AddrCache.ReleaseWrite;
  95. ipv6AddrCache.acquireRead := lockIpv6AddrCache.AcquireRead;
  96. ipv6AddrCache.releaseRead := lockIpv6AddrCache.ReleaseRead;
  97. END;
  98. END;
  99. END SetupLocks;
  100. PROCEDURE SetupSpinLocks(ipAddrCacheOnly: BOOLEAN);
  101. BEGIN
  102. IF ~ipAddrCacheOnly THEN
  103. (*
  104. setup link device-specific locks
  105. *)
  106. dev.acquireRx := AcquireDevRx;
  107. dev.releaseRx := ReleaseDevRx;
  108. dev.acquireTx := AcquireDevTx;
  109. dev.releaseTx := ReleaseDevTx;
  110. dev.rxPacketPool.acquire := AcquireDevRxPacketPool;
  111. dev.rxPacketPool.release := ReleaseDevRxPacketPool;
  112. dev.txPacketPool.acquire := AcquireDevTxPacketPool;
  113. dev.txPacketPool.release := ReleaseDevTxPacketPool;
  114. (*
  115. setup locks for interface-specific tasks management
  116. *)
  117. acquireTasks := AcquireTasks;
  118. releaseTasks := ReleaseTasks;
  119. ELSE
  120. (*
  121. setup locks for IP address resolution caches
  122. *)
  123. IF ipv4AddrCache # NIL THEN
  124. ipv4AddrCache.acquireWrite := AcquireIpv4AddrCache;
  125. ipv4AddrCache.releaseWrite := ReleaseIpv4AddrCache;
  126. ipv4AddrCache.acquireRead := AcquireIpv4AddrCache;
  127. ipv4AddrCache.releaseRead := ReleaseIpv4AddrCache;
  128. END;
  129. IF ipv6AddrCache # NIL THEN
  130. ipv6AddrCache.acquireWrite := AcquireIpv6AddrCache;
  131. ipv6AddrCache.releaseWrite := ReleaseIpv6AddrCache;
  132. ipv6AddrCache.acquireRead := AcquireIpv6AddrCache;
  133. ipv6AddrCache.releaseRead := ReleaseIpv6AddrCache;
  134. END;
  135. END;
  136. END SetupSpinLocks;
  137. PROCEDURE AcquireDevRx; BEGIN Machine.AcquireObject(lockDevRxFlag); END AcquireDevRx;
  138. PROCEDURE ReleaseDevRx; BEGIN Machine.ReleaseObject(lockDevRxFlag); END ReleaseDevRx;
  139. PROCEDURE AcquireDevTx; BEGIN Machine.AcquireObject(lockDevTxFlag); END AcquireDevTx;
  140. PROCEDURE ReleaseDevTx; BEGIN Machine.ReleaseObject(lockDevTxFlag); END ReleaseDevTx;
  141. PROCEDURE AcquireDevRxPacketPool; BEGIN Machine.AcquireObject(lockDevRxPacketPoolFlag); END AcquireDevRxPacketPool;
  142. PROCEDURE ReleaseDevRxPacketPool; BEGIN Machine.ReleaseObject(lockDevRxPacketPoolFlag); END ReleaseDevRxPacketPool;
  143. PROCEDURE AcquireDevTxPacketPool; BEGIN Machine.AcquireObject(lockDevTxPacketPoolFlag); END AcquireDevTxPacketPool;
  144. PROCEDURE ReleaseDevTxPacketPool; BEGIN Machine.ReleaseObject(lockDevTxPacketPoolFlag); END ReleaseDevTxPacketPool;
  145. PROCEDURE AcquireTasks; BEGIN Machine.AcquireObject(lockTasksFlag); END AcquireTasks;
  146. PROCEDURE ReleaseTasks; BEGIN Machine.ReleaseObject(lockTasksFlag); END ReleaseTasks;
  147. PROCEDURE AcquireIpv4AddrCache; BEGIN Machine.AcquireObject(lockIpv4AddrCacheFlag); END AcquireIpv4AddrCache;
  148. PROCEDURE ReleaseIpv4AddrCache; BEGIN Machine.ReleaseObject(lockIpv4AddrCacheFlag); END ReleaseIpv4AddrCache;
  149. PROCEDURE AcquireIpv6AddrCache; BEGIN Machine.AcquireObject(lockIpv6AddrCacheFlag); END AcquireIpv6AddrCache;
  150. PROCEDURE ReleaseIpv6AddrCache; BEGIN Machine.ReleaseObject(lockIpv6AddrCacheFlag); END ReleaseIpv6AddrCache;
  151. PROCEDURE Start*(intf: EnetBase.Interface; VAR res: Int): BOOLEAN;
  152. BEGIN
  153. ASSERT(alive);
  154. IF dev.start(dev,res) THEN
  155. BEGIN{EXCLUSIVE}
  156. waitingReq := FALSE;
  157. waiting := FALSE;
  158. END;
  159. RETURN TRUE;
  160. ELSE
  161. RETURN FALSE;
  162. END;
  163. END Start;
  164. PROCEDURE Stop*(intf: EnetBase.Interface; VAR res: Int): BOOLEAN;
  165. VAR b: BOOLEAN;
  166. BEGIN
  167. ASSERT(alive);
  168. BEGIN{EXCLUSIVE}
  169. waitingReq := TRUE;
  170. AWAIT(waiting);
  171. END;
  172. RETURN dev.stop(dev,res);
  173. END Stop;
  174. PROCEDURE Reset*(intf: EnetBase.Interface; VAR res: Int): BOOLEAN;
  175. VAR b: BOOLEAN;
  176. BEGIN
  177. ASSERT(alive);
  178. BEGIN{EXCLUSIVE}
  179. waitingReq := TRUE;
  180. AWAIT(waiting);
  181. END;
  182. RETURN dev.reset(dev,res);
  183. END Reset;
  184. PROCEDURE Finalize(intf: EnetBase.Interface; VAR res: Int): BOOLEAN;
  185. VAR b: BOOLEAN;
  186. BEGIN
  187. b := Stop(SELF,res);
  188. alive := FALSE;
  189. BEGIN{EXCLUSIVE}
  190. AWAIT(exited);
  191. END;
  192. RETURN b;
  193. END Finalize;
  194. BEGIN{ACTIVE,PRIORITY(Objects.High)}
  195. WHILE alive DO
  196. IF ~waitingReq THEN
  197. IF ~Interfaces.Update(SELF,res) THEN
  198. BEGIN{EXCLUSIVE} waitingReq := TRUE; END;
  199. END;
  200. ELSE
  201. BEGIN{EXCLUSIVE}
  202. waiting := TRUE;
  203. AWAIT(~waiting OR ~alive)
  204. END;
  205. END;
  206. END;
  207. BEGIN{EXCLUSIVE}
  208. exited := TRUE;
  209. END;
  210. END Interface;
  211. PROCEDURE AcquireIntfsWrite(); BEGIN Machine.AcquireObject(lockIntfsFlag); END AcquireIntfsWrite;
  212. PROCEDURE ReleaseIntfsWrite(); BEGIN Machine.ReleaseObject(lockIntfsFlag); END ReleaseIntfsWrite;
  213. PROCEDURE AcquireIntfsRead(); BEGIN Machine.AcquireObject(lockIntfsFlag); END AcquireIntfsRead;
  214. PROCEDURE ReleaseIntfsRead(); BEGIN Machine.ReleaseObject(lockIntfsFlag); END ReleaseIntfsRead;
  215. VAR
  216. lockIntfsFlag: BOOLEAN;
  217. lockIntfs: Locks.RWLock;
  218. BEGIN
  219. IF UseSpinLocks THEN
  220. Interfaces.acquireIntfsWrite := AcquireIntfsWrite;
  221. Interfaces.releaseIntfsWrite := ReleaseIntfsWrite;
  222. Interfaces.acquireIntfsRead := AcquireIntfsRead;
  223. Interfaces.releaseIntfsRead := ReleaseIntfsRead;
  224. ELSE
  225. NEW(lockIntfs);
  226. Interfaces.acquireIntfsWrite := lockIntfs.AcquireWrite;
  227. Interfaces.releaseIntfsWrite := lockIntfs.ReleaseWrite;
  228. Interfaces.acquireIntfsRead := lockIntfs.AcquireRead;
  229. Interfaces.releaseIntfsRead := lockIntfs.ReleaseRead;
  230. END;
  231. END Enet.