New handling of shared memory in new ACAPS
1 Previous situation
Two shared memory segments were created and accessed:
- one segment described by
struct AstroData
- one segment described by
struct ACAPSstatus
, this structure in turn had astruct DualPortedRAM
as its last member.
The combined size of these segments is of order 3000 bytes.
On Linux a shared memory segment has a typical minimum size of 1 page (4096 bytes), so it makes sense to create only one shared memory segment to hold both structures.
The dual ported RAM was a concept needed on OS-9 systems, there is really no need to treat this part differently. But in order to facilitate porting our legacy ACAPS code, I have kept that type of structure around.
At least the following programs were using the shared memory segments, and usually also local copies of them:
watchdog
loop
astra
sub
cid
display
Typically, the shared memory holding the struct ACAPSstatus
was
accessed via a struct ACAPSstatus *SysStat
, and the local copy via
struct ACAPSstatus acs
(note: not a pointer!)
2 Proposed new solution
The files
acaps.h
acapsdat.c
astrodat.h
astrodat.c
are replaced by
memory.h
memory.c
The memory layout in the shared segment is as follows:
struct MemoryLayout { struct AstroData oso; struct AcapsStatus acs; struct DualPortedRAM dp; /* no longer inside of AcapsStatus */ };
Note the new spelling of AcapsStatus
.
Linking your code with memory.c
, you get access to the following methods:
void createShared()
to link to the shared memory segment, create if necessary.void linkShared()
to link to the shared memory segment.void unlinkShared()
to unlink from the shared memory segment.void killShared()
to destroy the shared memory segment.void lockShared()
to block other programs from access via a semaphore.void unlockShared()
to allow access to other programs.
We should probably have a system service, which creates the shared memory during system boot.
To get pointers to the three structures in shared memory, use the following methods. They will all return a NULL pointer if one has not yet linked to the shared memory:
AstroData *sharedAstroData()
AcapsStatus *sharedAcapsStatus()
DualPortedRAM *sharedDualPortedRAM()
To get pointers to local copies, use the following methods, which are available even without linking to the shared segment:
AstroData *localAstroData()
AcapsStatus *localAcapsStatus()
DualPortedRAM *localDualPortedRAM()
Instead of old code like this
/* for local access */ struct ACAPSstatus acs; /* or extern struct ACAPSstatus acs; */ ... acs.dp.EncUsed = ENCBOTH; /* just as an example */ /* for shared access */ struct ACAPSstatus *SysStat; SysStat = LinkAcaps(); ... SysStat->dp.EncUsed = ENCBOTH; /* just as an example */
one now needs to use
/* for local access */ struct AcapsStatus *acs = localAcapsStatus(); ... acs->dp.EncUsed = ENCBOTH; /* acs now a pointer! */ /* for shared access */ linkShared(); ... struct AcapsStatus *SysStat = sharedAcapsStatus(); SysStat->dp.EncUsed = ENCBOTH; /* just as an example */
3 Consequences
- Programs
sub
anddisplay
have been modified (very few lines of code needed to be changed) and compile and link successfully. However, I suggest in the longer run we create an alternative todisplay
, which would consist of a GUI running onmunin
, and getting telescope status via MQTT. - Programs
watchdog
,loop
andastra
are currently being combined into one C++ program, which uses the new CANopen stack. Combining them into one process makes time synchronisation between them a lot easier and more reliable. This is work in progress. - Program
cid
has also been modified, but the old version made direct access to hardware interfaces. This needs to be decoupled, all access to hardware should be done by the program described under item 2.