0

I have two separate processes, a client and server process. They are linked using shared memory.

A client will begin his response by first altering a certain part of the shared memory to the input value and then flipping a bit indicating that the input is valid and that the value has not already been computed.

The server waits for a kill signal, or new data to come in. Right now the relevant server code looks like so:

 while(!((*metadata)&SERVER_KILL)){
        //while no kill signal
        bool valid_client = ((*metadata)&CLIENT_REQUEST_VALID)==CLIENT_REQUEST_VALID;
        bool not_already_finished = ((*metadata)&SERVER_RESPONSE_VALID)!=SERVER_RESPONSE_VALID;
        if(valid_client & not_already_finished){
                *int2 = sqrt(*int1);
                *metadata = *metadata | SERVER_RESPONSE_VALID;
                //place square root of input in memory, set
                //metadata to indicate value has been found
        }
 }

The problem with this is that the while loop takes up too many resources.

Most solutions to this problem are usually with a multithreaded application in which case you can use condition variables and mutexes to control the progression of the server process. Since these are single threaded applications, this solution is not applicable. Is there a lightweight solution that allows for waiting for these memory locations to change all while not completely occupying a hardware thread?

Chris
  • 566
  • 2
  • 7
  • 22
  • If you're on Linux, [this might help](https://stackoverflow.com/q/32338732/1270789). If you're on another OS, please state which it is. – Ken Y-N Jan 23 '18 at 03:21
  • On Windows, you can use [`WaitOnAddress()`](https://msdn.microsoft.com/en-us/library/windows/desktop/hh706898.aspx): "*Waits for the value at the specified address to change*". [Raymond Chen's blog](https://blogs.msdn.microsoft.com/oldnewthing/20160823-00/?p=94145) has articles on how to use it effectively. – Remy Lebeau Jan 23 '18 at 05:54

1 Answers1

0

You can poll or block... You can also wait for an interrupt, but that would probably also entail some polling or blocking.

Is message-passing on the table? That would allow you to block. Maybe a socket?

You can also send a signal from one process to another. You would write an interrupt handler for the receiving process.

Note that when an interrupt handler runs, it preempts the process' thread of execution. In other words, the main thread is paused while the handler runs. So your interrupt handler shouldn't grab a lock if there's a chance that the lock is already held, as it will create a deadlock situation. You can avoid this by using a re-entrant lock or one of the special lock types that disables interrupts before grabbing the lock. Things that grab locks: mutex.lock (obviously), I/O, allocating memory, condition.signal (much less obvious).

Humphrey Winnebago
  • 1,512
  • 8
  • 15