|
|
AROS Core Developer |
Joined: 14-Jun-2005 Posts: 377
From: Germany | | |
|
| @matthey
Quote:
I wonder what the logic was behind the Forbid/Permit macros. I would have thought they would have used a function to increment the Execbase counters and, if 0 or becoming not 0, write an interrupt mask value to one of the Paula registers to actually turn off/on whatever interrupts were necessary to disable multitasking (or all interrupts). |
No, you have mixed it. Forbid increases TDNestCnt byte value. If it is zero or greater than zero, then no new task will be rescheduled (preemption disabled). All interrupts remain enabled and may process. But if a reschedule would be requested (by interrupt for example, by means of sending a signal to task/process), it will be not "activated", only delayed reschedule request flag in SysBase will be set.
If, however, the task gives its CPU time by itself, e.g. by calling any function that waits (for signal, message, whatever), it will be rescheduled (call it cooperative part of multitasking). Once the task gets CPU time again, the systems TDNestCnt will be set again to the previous value.
When Permit() is called, TDnestCnt is decreased. If it turns from 0 to -1, scheduler will be eventually called (if it was actually requested) and task switch can occur.
Now what you described was Disable()/Enable() pair. During Disable call all interrupts are unconditionally disabled and IDNestCnt byte is increased. During Enable() call IDNestCnt is decreased and if it turns from 0 to -1, interrupts will be re-enabled.
So, to summarise, Forbid()/Permit() disables scheduler only, guaranteeing that the task will run uninterrupted by other tasks. Usable when e.g. several tasks want to access one shared resource of any kind. Disable()/Enable() effectively disables interrupts (and thus the scheduler too, since it is driven by vertical blank interrupt) guaranteeing exclusive access to resource which could be otherwise accessed both by task and/or interrupt handlers. |
|