The Plot And Problem Both Thicken
The Modbus slave driver (interesting function categorization) utilizes the modbus_mapping_t structure type to contain each of the four types of data it can process: bits, input bits, registers and input registers. Each of these point to a contiguous block of memory allocated of either uint8_t or uint16_t, depending on the bits or bytes parts. The way I have my data blocks set up, they need not necessarily be contiguous nor present necessarily. This creates a problem though, when I try to blend the two systems of storing these data types together.
Thinking It Through
Because I want to be able to have multiple slaves serve data off the same block, we have the conundrum of where that block resides. On the one hand I could create a modbus_mapping_t structure within the RTU structure of each virtual Slave RTU, and could cross-link other RTU masters with that block, along with the DataBlocks to pull the VINT data from them. Maybe a better solution is to create external modbus blocks. If I remove my concept of a datablock (which is really just a subset of the main block of data) and create raw blocks of data as the data blocks instead, we could point VINTs at them using the newly implemented value arrays. Imagine then, we create a datablock of, say, a thousand bits and a thousand bytes for each of the pairs of input and output coils and registers within our virtual RTU slave. Now we can point our modbus_reply() function to this block of data, or we can point multiple RTUs at it. Then, we create new construct - maybe called something like a Section, Tag or Subset - which contains a starting address and a length parameter, referencing one of our main blocks of data. This Section gets a single VINT for it's value, but it will make proper use of the array functionality of VINTs now that this has been implemented. We add a Device Status VINT for the entire section (since one is enough) and we have our access in and out of the global data blocks, satisfying both needs with efficiency!
The one last piece of the puzzle is data concurrency; race conditions and how to prevent them. Since multiple virtual and/or real RTU devices may be accessing the same block of memory, how can we ensure only one uses it at a time, especially when the reply() function potentially blocks? We might be able to use 0 timeout values, gather up all the sockfd's from each RTU device and run them through our own select() call. For that matter, we might single-thread the entire modbus plugin, which would eliminate the need for the locks at all. Interesting. A little daunting, but very interesting...