123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- MODULE Enet; (** AUTHOR ""; PURPOSE ""; *)
- IMPORT
- EnetBase, EnetTiming, EnetArp, EnetIcmp, EnetUdp, Objects, Locks, Kernel, Machine, Interfaces := EnetInterfaces, Trace;
- CONST
- MaxNumInterfaces* = 2; (** maximal supported number of interfaces *)
- MaxArpCacheSize* = 256;
- UseSpinLocks* = TRUE; (** TRUE for forcing the use of spin locks *)
- TYPE
- Int32 = EnetBase.Int32;
- Int16 = EnetBase.Int16;
- Int = EnetBase.Int;
- Interface* = OBJECT(EnetBase.Interface)
- VAR
- res: Int;
- alive: BOOLEAN;
- exited: BOOLEAN;
- waiting, waitingReq: BOOLEAN;
- lockDevRxFlag, lockDevTxFlag: BOOLEAN;
- lockDevRxPacketPoolFlag, lockDevTxPacketPoolFlag: BOOLEAN;
- lockTasksFlag: BOOLEAN;
- lockIpv4AddrCacheFlag, lockIpv6AddrCacheFlag: BOOLEAN;
- lockDevRx, lockDevTx: Locks.Lock;
- lockDevRxPacketPool, lockDevTxPacketPool: Locks.Lock;
- lockTasks: Locks.Lock;
- lockIpv4AddrCache, lockIpv6AddrCache: Locks.RWLock;
- PROCEDURE &InitInterface*(
- dev: EnetBase.LinkDevice;
- VAR res: Int
- );
- BEGIN
- IF ~Interfaces.InitInterface(SELF,dev,res) THEN RETURN; END;
- IF UseSpinLocks THEN SetupSpinLocks(FALSE); ELSE SetupLocks(FALSE); END;
- (*
- setup support of basic protocols
- *)
- EnetArp.Install(SELF);
- EnetIcmp.Install(SELF);
- EnetUdp.Install(SELF);
- IF UseSpinLocks THEN SetupSpinLocks(TRUE); ELSE SetupLocks(TRUE); END;
- (*
- setup interface-specific methods
- *)
- start := Start;
- stop := Stop;
- reset := Reset;
- finalize := Finalize;
- IF res = 0 THEN
- alive := TRUE;
- waitingReq := TRUE;
- waiting := TRUE;
- exited := FALSE;
- ELSE
- alive := FALSE;
- END;
- END InitInterface;
- PROCEDURE SetupLocks(ipAddrCacheOnly: BOOLEAN);
- BEGIN
- IF ~ipAddrCacheOnly THEN
- NEW(lockDevRx);
- NEW(lockDevTx);
- NEW(lockDevRxPacketPool);
- NEW(lockDevTxPacketPool);
- NEW(lockTasks);
- (*
- setup link device-specific locks
- *)
- dev.acquireRx := lockDevRx.Acquire;
- dev.releaseRx := lockDevRx.Release;
- dev.acquireTx := lockDevTx.Acquire;
- dev.releaseTx := lockDevTx.Release;
- dev.rxPacketPool.acquire := lockDevRxPacketPool.Acquire;
- dev.rxPacketPool.release := lockDevRxPacketPool.Release;
- dev.txPacketPool.acquire := lockDevTxPacketPool.Acquire;
- dev.txPacketPool.release := lockDevTxPacketPool.Release;
- (*
- setup locks for interface-specific tasks management
- *)
- acquireTasks := lockTasks.Acquire;
- releaseTasks := lockTasks.Release;
- ELSE
- NEW(lockIpv4AddrCache);
- NEW(lockIpv6AddrCache);
- (*
- setup locks for IP address resolution caches
- *)
- IF ipv4AddrCache # NIL THEN
- ipv4AddrCache.acquireWrite := lockIpv4AddrCache.AcquireWrite;
- ipv4AddrCache.releaseWrite := lockIpv4AddrCache.ReleaseWrite;
- ipv4AddrCache.acquireRead := lockIpv4AddrCache.AcquireRead;
- ipv4AddrCache.releaseRead := lockIpv4AddrCache.ReleaseRead;
- END;
- IF ipv6AddrCache # NIL THEN
- ipv6AddrCache.acquireWrite := lockIpv6AddrCache.AcquireWrite;
- ipv6AddrCache.releaseWrite := lockIpv6AddrCache.ReleaseWrite;
- ipv6AddrCache.acquireRead := lockIpv6AddrCache.AcquireRead;
- ipv6AddrCache.releaseRead := lockIpv6AddrCache.ReleaseRead;
- END;
- END;
- END SetupLocks;
- PROCEDURE SetupSpinLocks(ipAddrCacheOnly: BOOLEAN);
- BEGIN
- IF ~ipAddrCacheOnly THEN
- (*
- setup link device-specific locks
- *)
- dev.acquireRx := AcquireDevRx;
- dev.releaseRx := ReleaseDevRx;
- dev.acquireTx := AcquireDevTx;
- dev.releaseTx := ReleaseDevTx;
- dev.rxPacketPool.acquire := AcquireDevRxPacketPool;
- dev.rxPacketPool.release := ReleaseDevRxPacketPool;
- dev.txPacketPool.acquire := AcquireDevTxPacketPool;
- dev.txPacketPool.release := ReleaseDevTxPacketPool;
- (*
- setup locks for interface-specific tasks management
- *)
- acquireTasks := AcquireTasks;
- releaseTasks := ReleaseTasks;
- ELSE
- (*
- setup locks for IP address resolution caches
- *)
- IF ipv4AddrCache # NIL THEN
- ipv4AddrCache.acquireWrite := AcquireIpv4AddrCache;
- ipv4AddrCache.releaseWrite := ReleaseIpv4AddrCache;
- ipv4AddrCache.acquireRead := AcquireIpv4AddrCache;
- ipv4AddrCache.releaseRead := ReleaseIpv4AddrCache;
- END;
- IF ipv6AddrCache # NIL THEN
- ipv6AddrCache.acquireWrite := AcquireIpv6AddrCache;
- ipv6AddrCache.releaseWrite := ReleaseIpv6AddrCache;
- ipv6AddrCache.acquireRead := AcquireIpv6AddrCache;
- ipv6AddrCache.releaseRead := ReleaseIpv6AddrCache;
- END;
- END;
- END SetupSpinLocks;
- PROCEDURE AcquireDevRx; BEGIN Machine.AcquireObject(lockDevRxFlag); END AcquireDevRx;
- PROCEDURE ReleaseDevRx; BEGIN Machine.ReleaseObject(lockDevRxFlag); END ReleaseDevRx;
- PROCEDURE AcquireDevTx; BEGIN Machine.AcquireObject(lockDevTxFlag); END AcquireDevTx;
- PROCEDURE ReleaseDevTx; BEGIN Machine.ReleaseObject(lockDevTxFlag); END ReleaseDevTx;
- PROCEDURE AcquireDevRxPacketPool; BEGIN Machine.AcquireObject(lockDevRxPacketPoolFlag); END AcquireDevRxPacketPool;
- PROCEDURE ReleaseDevRxPacketPool; BEGIN Machine.ReleaseObject(lockDevRxPacketPoolFlag); END ReleaseDevRxPacketPool;
- PROCEDURE AcquireDevTxPacketPool; BEGIN Machine.AcquireObject(lockDevTxPacketPoolFlag); END AcquireDevTxPacketPool;
- PROCEDURE ReleaseDevTxPacketPool; BEGIN Machine.ReleaseObject(lockDevTxPacketPoolFlag); END ReleaseDevTxPacketPool;
- PROCEDURE AcquireTasks; BEGIN Machine.AcquireObject(lockTasksFlag); END AcquireTasks;
- PROCEDURE ReleaseTasks; BEGIN Machine.ReleaseObject(lockTasksFlag); END ReleaseTasks;
- PROCEDURE AcquireIpv4AddrCache; BEGIN Machine.AcquireObject(lockIpv4AddrCacheFlag); END AcquireIpv4AddrCache;
- PROCEDURE ReleaseIpv4AddrCache; BEGIN Machine.ReleaseObject(lockIpv4AddrCacheFlag); END ReleaseIpv4AddrCache;
- PROCEDURE AcquireIpv6AddrCache; BEGIN Machine.AcquireObject(lockIpv6AddrCacheFlag); END AcquireIpv6AddrCache;
- PROCEDURE ReleaseIpv6AddrCache; BEGIN Machine.ReleaseObject(lockIpv6AddrCacheFlag); END ReleaseIpv6AddrCache;
- PROCEDURE Start*(intf: EnetBase.Interface; VAR res: Int): BOOLEAN;
- BEGIN
- ASSERT(alive);
- IF dev.start(dev,res) THEN
- BEGIN{EXCLUSIVE}
- waitingReq := FALSE;
- waiting := FALSE;
- END;
- RETURN TRUE;
- ELSE
- RETURN FALSE;
- END;
- END Start;
- PROCEDURE Stop*(intf: EnetBase.Interface; VAR res: Int): BOOLEAN;
- VAR b: BOOLEAN;
- BEGIN
- ASSERT(alive);
- BEGIN{EXCLUSIVE}
- waitingReq := TRUE;
- AWAIT(waiting);
- END;
- RETURN dev.stop(dev,res);
- END Stop;
- PROCEDURE Reset*(intf: EnetBase.Interface; VAR res: Int): BOOLEAN;
- VAR b: BOOLEAN;
- BEGIN
- ASSERT(alive);
- BEGIN{EXCLUSIVE}
- waitingReq := TRUE;
- AWAIT(waiting);
- END;
- RETURN dev.reset(dev,res);
- END Reset;
- PROCEDURE Finalize(intf: EnetBase.Interface; VAR res: Int): BOOLEAN;
- VAR b: BOOLEAN;
- BEGIN
- b := Stop(SELF,res);
- alive := FALSE;
- BEGIN{EXCLUSIVE}
- AWAIT(exited);
- END;
- RETURN b;
- END Finalize;
- BEGIN{ACTIVE,PRIORITY(Objects.High)}
- WHILE alive DO
- IF ~waitingReq THEN
- IF ~Interfaces.Update(SELF,res) THEN
- BEGIN{EXCLUSIVE} waitingReq := TRUE; END;
- END;
- ELSE
- BEGIN{EXCLUSIVE}
- waiting := TRUE;
- AWAIT(~waiting OR ~alive)
- END;
- END;
- END;
- BEGIN{EXCLUSIVE}
- exited := TRUE;
- END;
- END Interface;
- PROCEDURE AcquireIntfsWrite(); BEGIN Machine.AcquireObject(lockIntfsFlag); END AcquireIntfsWrite;
- PROCEDURE ReleaseIntfsWrite(); BEGIN Machine.ReleaseObject(lockIntfsFlag); END ReleaseIntfsWrite;
- PROCEDURE AcquireIntfsRead(); BEGIN Machine.AcquireObject(lockIntfsFlag); END AcquireIntfsRead;
- PROCEDURE ReleaseIntfsRead(); BEGIN Machine.ReleaseObject(lockIntfsFlag); END ReleaseIntfsRead;
- VAR
- lockIntfsFlag: BOOLEAN;
- lockIntfs: Locks.RWLock;
- BEGIN
- IF UseSpinLocks THEN
- Interfaces.acquireIntfsWrite := AcquireIntfsWrite;
- Interfaces.releaseIntfsWrite := ReleaseIntfsWrite;
- Interfaces.acquireIntfsRead := AcquireIntfsRead;
- Interfaces.releaseIntfsRead := ReleaseIntfsRead;
- ELSE
- NEW(lockIntfs);
- Interfaces.acquireIntfsWrite := lockIntfs.AcquireWrite;
- Interfaces.releaseIntfsWrite := lockIntfs.ReleaseWrite;
- Interfaces.acquireIntfsRead := lockIntfs.AcquireRead;
- Interfaces.releaseIntfsRead := lockIntfs.ReleaseRead;
- END;
- END Enet.
|