What you may need, in addition to the dual-port RAM, is a mailbox-interrupt peripheral. It would look like a 16- or 32-bit PIO register, but writing to it on the producer side would generate an interrupt to the consumer side, and reading from the consumer side (or something like that) would clear the interrupt.
If you don't want to write a custom peripheral, there is a way to do it with PIOs. Create one PIO with 8 or 16 outputs for the producer. Create a PIO with the same number of inputs and outputs (not bidirectional pins) and a level-detecting IRQ for the consumer. Connect the external I/Os with a subtracter: consumer input = producer output - consumer output.
The producer needs to have a shadow variable with the last value written to its PIO. When it wants to wake up the consumer, it increments this shadow variable and writes the result to the PIO.
The consumer also has a shadow variable with the contents of its PIO. It initializes the edge detection to interrupt whenever the input is not all 0's. The IRQ handler reads the PIO to determine the number of events since the last time it was handled. It can then do one of two things:[list][*]Add this number to its shadow variable and write the result back to its PIO, or
[*]Loop, incrementing the shadow variable each time and writing it back, until the value read back is 0.
[/list]Note that the number of PIO bits used determines the maximum number of pending events; size it appropriately. I think this design is race-proof; if not, someone please show me what will break it.
Note to Altera: it would be nice to have a peripheral that does this; one peripheral with two slave ports. The HAL driver would be a character driver; you write characters to the producer device (one character increments the counter by 1; the actual character is ignored) and read characters from the consumer device. I don't remember if there is a select()-like call in HAL, though.