Remove/Change Disable()-Enable() into....?

11 posts / 0 new
Last post
jabirulo
jabirulo's picture
Offline
Last seen: 1 month 1 week ago
Joined: 2013-05-30 00:53
Remove/Change Disable()-Enable() into....?

Hi just seeing that in MIXER sources (own soundcards drivers) uses DISABLE()/ENABLE() function want to know if it's possible (and safe) to change'em with a mutex/semaphore or just remove from code as they are not important/usefull.

Disable/Enable are on 3 _ctrl.c sources: emu10kx_ctrl.c, fm801_ctrl.c and sb128_ctrl.c

On emu10kx_ctrl.c, fm801_ctrl.c they are commented out (by me, since V1.39 or alike) and seems ok, as nobody complained "system freezes, doesn't work for me now,....):

void codec_write(unsigned short reg, unsigned short val)
{
 int i;
 
 //IExec->Disable();
 for(i = 0; i < 10000; i++)
  if( !(dev->InWord(iobase + FM801_AC97_CMD) & (1<<9)) )
   goto ok1;
#ifdef _DEBUG_
 IExec->DebugPrintF("Couldn't write to ac97!\n");
#endif
ok1:
 dev->OutWord(iobase + FM801_AC97_DATA, val);
 dev->OutWord(iobase + FM801_AC97_CMD, reg);
 //IExec->Enable();
}
 
 
void codec_write(unsigned short reg, unsigned short val)
{
 //Disable();
 if(Audigy == FALSE)
 {
  dev->OutByte(iobase + AC97ADDRESS, reg);
  dev->OutWord(iobase + AC97DATA, val);
 }
 else
  emu10k1_set_volume_gpr(reg, val);
 
 //Enable();
}

Is it ok to just comment out? Or is better coding to change'em to use Mutex/Semaphore?

TIA

Massi
Massi's picture
Offline
Last seen: 4 years 7 months ago
Joined: 2012-03-28 17:16
@jabirulo Well I am not

@jabirulo

Well I am not really into the Mixer source code, anyway.

This reading can be of help (Disabling Tasks)
http://wiki.amigaos.net/wiki/Exec_Tasks
Basically disabling is required when a task accesses structures that are shared by interrupt code.

Thus the fact that no one complained after you commented those statements out doesn' t necessarily mean that it is garanteed to always work well.

salass00
salass00's picture
Offline
Last seen: 7 months 1 day ago
Joined: 2011-02-03 11:27
@jabirulo I'm pretty sure

@jabirulo

I'm pretty sure you should not comment out those calls. The point is to sure that the AHI driver's interrupt code (or any other code for that matter) doesn't interfere while Mixer is writing to the audio h/w. While disabling all interrupts is overkill it's probably the only way to do this in a safe manner from a program that doesn't know anything about the inner workings of AHI or its drivers.

Ideally the mixer functionality should be done inside AHI and it's drivers and Mixer would simply be a program making use of this.

Massi
Massi's picture
Offline
Last seen: 4 years 7 months ago
Joined: 2012-03-28 17:16
@jabirulo Mutexes and

@jabirulo

Mutexes and Semaphores only make sense when all the involved tasks use the same locking convention accessing shared data and this is not the case.

Be also aware that disabling interrupts is not a good practice in a multitasking environment like AmigaOS4, but it is probably the only possible way for your purposes, as salass00 said.

I would then restore those commented statements.

jabirulo
jabirulo's picture
Offline
Last seen: 1 month 1 week ago
Joined: 2013-05-30 00:53
@all THX for explanations,

@all
THX for explanations, will restore such Disable/Enable functions in next MIXER update.

AOS4.1/SAM460ex/PPC460EX-1155MHZ/2048MB/RadeonHD6570/SSD120GB/DVDRW :-P

hypex
hypex's picture
Offline
Last seen: 4 months 1 week ago
Joined: 2011-09-09 16:20
I wonder if another alternate

I wonder if another alternate is to use a soft interrupt routine instead. This would work above a Forbid() level by running higher than a task and the code would run without interruption. :-)

However, it does have a priority so could be below the desire Disable() level.

Syill, it's would avoid disabling multitasking and common OS like DOS and Linux used this type of function call that called a kernel routine interrupt vector.

salass00
salass00's picture
Offline
Last seen: 7 months 1 day ago
Joined: 2011-02-03 11:27
I wonder if another alternate


I wonder if another alternate is to use a soft interrupt routine instead. This would work above a Forbid() level by running higher than a task and the code would run without interruption. :-)

This wouldn't help since interrupts can still be interrupted by higher level interrupts which in the case of software interrupts would be all h/w interrupts.

You could use Disable() but then you would be where you were before but with the added problem that if you do anything that causes a DSI or ISI inside a software interrupt it will cause the whole OS to crash rather than just your one program.

hypex
hypex's picture
Offline
Last seen: 4 months 1 week ago
Joined: 2011-09-09 16:20
This wouldn't help since

This wouldn't help since interrupts can still be interrupted by higher level interrupts which in the case of software interrupts would be all h/w interrupts.

Good point. Just when I thought that sort of thing would only happen on actual Amiga hardware when considering the original Amiga interrupts.

Still, for other code that needs protection, it could be an alternate to disabling multitasking. If a semaphore or mutex wasn't suitable.

Massi
Massi's picture
Offline
Last seen: 4 years 7 months ago
Joined: 2012-03-28 17:16
@hypex Overall disabling

@hypex

Overall disabling multitasking in a multitasking environment is not an advisable practice either.

Semaphores / mutexes only make sense when the involved concurrent "parts" agree on the same locking policy.

xenic
xenic's picture
Offline
Last seen: 2 years 7 months ago
Joined: 2011-05-07 04:52
@jabirulo There are specific

@jabirulo
There are specific instances where enable()/disable() should be used. I can't tell for sure but the "reg" variable makes it look like some of the code you mention is read/writing system or card registers. Reading/writing to registers should usually be done as an atomic operation (it appears to the rest of the system to occur instantaneously).
In this code:

dev->OutByte(iobase + AC97ADDRESS, reg);
dev->OutWord(iobase + AC97DATA, val);

it looks like a data direction register is written to; followed by a write to the data register. If that operation is interrupted before completion the results are unpredictable and could lead to failure.

On the other hand this code:

for(i = 0; i < 10000; i++)
if( !(dev->InWord(iobase + FM801_AC97_CMD) & (1<<9)) )
goto ok1;
#ifdef _DEBUG_
IExec->DebugPrintF("Couldn't write to ac97!\n");
#endif

is potentially doing 10000 loop iterations and possibly debug output while interrupts are disabled which seems like a bad idea to me. I'm not an expert but in that case, I would only use disable()/enable() around the write operation below that code. I think you might be better off consulting someone who has experience accessing hardware registers like Lyle Hazelwood.

X1000 - OS 4.1FE

LyleHaze
LyleHaze's picture
Offline
Last seen: 2 years 1 month ago
Joined: 2011-05-26 03:58
You are right on target. Most

You are right on target.
Most audio cards appear in PCI space.
The drivers usually set up a hardware interrupt that gets kicked at the end of each buffer.
That interrupt calls driver code, which calls AHI for "more audio" and refills the buffer.
There are no provisions made for sharing the audio card with other programs, like Mixer.

So the largest part of executable code is driven from hard interrupts.

Since there is no provision for mutual exclusion made in each audio driver, there's no way I can think of to prevent collisions.

Some of this may change for newer devices that don't generate hard interrupts to refill their buffers, like USB audio devices or HDAudio devices, which don't appear in PCI space directly. But that doesn't solve todays question.

If we could do it all over again, I can think of a few things to do differently. But then it wouldn't be AHI, would it?

LyleHaze

Log in or register to post comments