@amigaksi
If the semaphore involves something critical which you are allowing a lower priority task to do then there's nothing wrong with that.
I think that depends on the intent of the code. In this case, I'm polling hardware. As 680x0 Amigas don't have an idle loop, I'm using a low priority task (-128) to simulate idle-time polling; however, I have a higher priority task that attempts to guarantee at least some amount of polling occurs prior to a soft deadline.
Neither task can poll the hardware at the same time, so I need to use a semaphore to coordinate the work. If a medium priority task is running while the low priority task holds the semaphore, the high priority task doesn't run, and the deadline is not met, i.e. priority inversion.
In this specific case, the high priority task has prior knowledge about the low priority task and can manage the low priority task's priority accordingly. The problem started me thinking about the general case, though, and how it might be solved.
Other solutions to my scheduling problem involve the use of hardware interrupts (vblank for interval timing), software interrupts (implicit synchronization), timers (soft real-time scheduling), etc. All have tradeoffs. I haven't done the math yet--I'm treating the software controlling the hardware like a real-time subsystem--so I'm still not sure what arrangement of tasks will meet my needs.