Login
Username:

Password:

Remember me



Lost Password?

Register now!

Sections

Who's Online
166 user(s) are online (146 user(s) are browsing Forums)

Members: 1
Guests: 165

hotrod, more...

Support us!

Headlines

 
  Register To Post  

« 1 2 3 (4) 5 6 »
Re: Tracing
Home away from home
Home away from home


See User information
@kas1e

>You need to make the trace collection function not depend on any globals and pass the process id to trace via a message

That won’t really work, by the time you get message, the task your monitoring is at different location in its program. So you will probably get poor stack traces.

(NutsAboutAmiga)

Basilisk II for AmigaOS4
AmigaInputAnywhere
Excalibur
and other tools and apps.
Go to top
Re: Tracing
Home away from home
Home away from home


See User information
@All
Ok, so, i probably do something very wrong (as i simply crashes now once reached the code sending the message from patched CallHookPkt), but there it is:

At top (out of any functions, so kind of global still?) create:

struct ProcessIDMessage {
    
struct Message msg;
    
ULONG processID;
};

struct MsgPort *mainPort;


Now in the main() cookie up loop based on this:
https://wiki.amigaos.net/wiki/Exec_Messages_and_Ports

.....ba;blabla...

    
BOOL ABORT FALSE;
    
struct ProcessIDMessage *receivedMessage NULL;
    
    
mainPort IExec->AllocSysObjectTags(ASOT_PORTTAG_END);

    if(
mainPort != NULL)
    {
        
        
uint32 portsig 1U << mainPort->mp_SigBit;
        
uint32 usersig SIGBREAKF_CTRL_C;
        
        while(
ABORT == FALSE)
        {
            
uint32 signal IExec->Wait(portsig usersig);

            if (
signal portsig)
            {
                
IExec->DebugPrintF("port signal\n");
 
                while(
receivedMessage = (struct ProcessIDMessage *)IExec->GetMsg(mainPort))
                {
                    
IExec->DebugPrintF("mainport received: ProcessID = %lu\n"receivedMessage->processID);
                    
IExec->ReplyMsg((struct Message *)receivedMessage);
                }
            }

            if (
signal usersig)
            {
                
IExec->DebugPrintF("ctrl+c signal\n");
                while(
receivedMessage = (struct ProcessIDMessage *)IExec->GetMsg(mainPort)) { // make sure port is empty
                    
IExec->ReplyMsg((struct Message *)receivedMessage);
                }    
                
ABORT TRUE;
            }
        }

    }


// deinit ---

    
IExec->DebugPrintF("----Deinit!\n");

//IPC:
    
IExec->FreeSysObject(ASOT_MESSAGEreceivedMessage);
    
IExec->FreeSysObject(ASOT_PORTmainPort);

.....
balbalbal....


And then, in Patched CallHookPkt doing that:

if(!stricmp(buffer,traced_binary)) 
                {
                        if (&
process->pr_Task != NULL)
                        {
                                if (
hookstack != NULL)
                                {    
                                    
// old global/bad way:
                                    // process_to_inspect = process;

                                    // messages one:
                                    
struct ProcessIDMessage *message = (struct ProcessIDMessage *)IExec->AllocSysObjectTags(ASOT_MESSAGEASOMSG_Sizesizeof(struct ProcessIDMessage), ASOMSG_ReplyPortmainPortTAG_END); 
                                    if (
message != NULL) {
                                            
message->processID process->pr_ProcessID// Get the process ID here
                                    
}

                                    
IExec->PutMsg(mainPort, (struct Message *)message);
                                    
                                    
IExec->FreeSysObject(ASOT_MESSAGEmessage);
                                    

                                    
IExec->DebugPrintF("CallHookPkt call # %d\n"callhookspkt_counts++);
                                }



So with that, once i reach first time patched CallHookPkt, and it send the message i simple crashes. If i add (for sake of tests) some Delay(5) in this part, i can see that my ProcessID always 155, and that seems whole messaging combo didn't works as expected. But i surely miss something trivial..

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: Tracing
Just popping in
Just popping in


See User information
@kas1e

I think I know why your Tracing crashes
In your CallHookPt you are Freeing the message after PutMsg, before the receiver had time to process it.

Go to top
Re: Tracing
Not too shy to talk
Not too shy to talk


See User information
@LiveForIt

Quote:
I don’t know why you want your code to have more likely bugs.


Well, I haven't started doing it yet, but it's the next best thing to a union.

Quote:
now image you pointer is NULL, first is offset 0, 2en is offset 4, now image if member is 2en.


Obviously to avoid that the "ptr" would be tested as being valid first.

Quote:
The only thing you need to do, to screw up your code, is add a new member at the beginning of your struct, and your code breaks.


A new member can't be added because a Task must remain static. Process can be extended but a Process is always a subclass of Task and the Task superclass cannot be changed. In any case this works because the first member of a Process is a Task. The same way it can work if it was passed to a function expecting a Node and the Node field specified.

Go to top
Re: Tracing
Not too shy to talk
Not too shy to talk


See User information
@joerg

Quote:
At least for 99% of the OS4 code doesn't use direct function calls but always goes through the interface of the library.


That would be rather inefficient and slow it down. In particular Intuition used to call internal functions. I used to peek and poke a lot. Being C it stacked a lot of parameters and using internal functions avoided stacking registers. But if OS4 doesn't call internally the same way then it will incur the double direction of jump table calls OS4 gets criticised for.

Quote:
On OS4 VARARGS68K and va_(get|start)linearva does that. It was required for compatibility to emulated m68k code passing the arguments on the stack and it's used for example for all of the varargs TagItem functions.


I noticed those VARARGSS68K but I didn't see why they were necessary. Any emulation of 68K var args is internally to the emulators so shouldn't need to be exposed. Aside from that varargs are a common function practice in portable C code that can run on x86 or PPC and others so varargs never looked 68K exclusive to me.

Go to top
Re: Tracing
Not too shy to talk
Not too shy to talk


See User information
@kas1e

Quote:
In other words, even if we know that we can do something because of jump table and interfaces, we still dont know for now how to detect what function of the stacktraced library (at least library) were called :(


Unless the function prologue is on the stack frame no it cannot be known exactly. An exact address in the interface can be matched to that offset easily and a name found. Well, after walking a whole list, which is one way about it.

With an offset not matching an exact function jump, then it's harder and looking for closest in jump table. So bit of work. And it still can be a best guess to pin point it.

Quote:
So with that, once i reach first time patched CallHookPkt, and it send the message i simple crashes. If i add (for sake of tests) some Delay(5) in this part, i can see that my ProcessID always 155, and that seems whole messaging combo didn't works as expected. But i surely miss something trivial..


You've done two funny things and perhaps even three.

struct ProcessIDMessage *message = (struct ProcessIDMessage *)IExec->AllocSysObjectTags(ASOT_MESSAGEASOMSG_Sizesizeof(struct ProcessIDMessage), ASOMSG_ReplyPortmainPortTAG_END);


Aside from the allocation overhead this would be fine, except for one thing. You've set the reply port as your main port. When your main task replies it back it will be endlessly sent back to your main task!

You need a local port to give it a reply port. The info will be in the SDK. Now you can avoid creating a reply port by using ASOPORT_Signal in the tags. One tag you will need to give and you can just supply a signal. You will need a signal. You don't know if all signals are taken so it might break getting another one. Just avoid it and use SIGF_SINGLE. Free for single use.

IExec->PutMsg(mainPort, (struct Message *)message);                                                                      IExec->FreeSysObject(ASOT_MESSAGEmessage);


You didn't wait for the message to be processed!

So was this hard crash? Sending a message then instantly freeing memory tends to freeze OS. PutMsg() is very senstive.

So you need to wait for that reply. That be a reply port which will overcomplicate it. Or just specify a signal and simplify it. I like this way.

IExec->SetSignal(0SIGF_SINGLE);
IExec->PutMsg(mainPort, (struct Message *)message);  
IExec->Wait(SIGF_SINGLE);


https://wiki.amigaos.net/wiki/Exec_Signals

Go to top
Re: Tracing
Home away from home
Home away from home


See User information
@Hypex
Thanks for the answer, but I need some clarification:

You say i need local port to give a reply port, but I can avoid it, while can't (as i need it), but instead create it by some other than AllocSysObjectTags way as it have “allocation overhead” ? Or what you mean exactly ?

As i understand it, you still suggest to use for AllocSysObjectTags also ASOPORT_Signal when allocation for message, and this mean i can not create second reply port, and handle it without ? (sounds strange!) But what about “allocation overhead” which you mention, then if AllocSysObjectTags() still should be used for ?

Then i tried like this, and while it didn't crash, it didn't work, it just stuck on the first receive.

struct ProcessIDMessage *message = (struct ProcessIDMessage *)IExec->AllocSysObjectTags(ASOT_MESSAGEASOMSG_Sizesizeof(struct ProcessIDMessage), ASOPORT_AllocSigFALSEASOPORT_SignalSIGB_SINGLETAG_DONE);
                                    if (
message != NULL) {
                                            
message->processID process->pr_ProcessID// Get the process ID here
                                    
}                            
                                    
IExec->SetSignal(0SIGF_SINGLE);
                                    
IExec->PutMsg(mainPort, (struct Message *)message);
                                    
IExec->Wait(SIGF_SINGLE);


The main()'s code is not changed, of course. Hope you wasn't mean that i need to change that too and fully rewrite it to handle new sort of signal without receiving a reply ?:)

And where is FreeSysObject() in your example ? Should't it be right after Wait(SIGF_SINGLE) ?

ps. Never touched anything with all this messages, but after reading wiki were under impression that for communicate between 2 tasks i need one single port , in which i do this communication by messages, not that i need different port for each messages which should be send from one task to another..


Edited by kas1e on 2024/5/7 19:43:13
Edited by kas1e on 2024/5/7 19:45:56
Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: Tracing
Quite a regular
Quite a regular


See User information
@kas1e
Your hook function runs in the caller task while your main runs in your own task. You have to stop the caller after messaging the main task until the main task finishes collecting the stack trace otherwise the caller continues and may exit or will not be at the place you want to trace. There are several ways to do that:
1. Reply with a message, the caller needs a message port for that in addition to the main's message port where you call it.
2. Wait for a signal, then the main task needs to raise the signal (don't know what's the corect term for that in AmigaOS) once finished to make the caller continue.
3. or maybe in the hooked function call suspend self after sending the message and from the main task call restart for the process ID that was passed in the message, then you won't need either a reply message port nor a signal.

Go to top
Re: Tracing
Home away from home
Home away from home


See User information
@balaton
Quote:

. or maybe in the hooked function call suspend self after sending the message and from the main task call restart for the process ID that was passed in the message, then you won't need either a reply message port nor a signal.


That looks like the way to go , and sounds more easy!

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: Tracing
Home away from home
Home away from home


See User information
never mind

(NutsAboutAmiga)

Basilisk II for AmigaOS4
AmigaInputAnywhere
Excalibur
and other tools and apps.
Go to top
Re: Tracing
Not too shy to talk
Not too shy to talk


See User information
@kas1e

Quote:
You say i need local port to give a reply port, but I can avoid it, while can't (as i need it), but instead create it by some other than AllocSysObjectTags way as it have “allocation overhead” ? Or what you mean exactly ?


Sorry was typing reply in a rush before bed time.

Okay so by local port I meant a port local to your patched function. You don't necessarily need a port, it's just the messaging system is designed in a two way fashion, so a message is sent to a task and that task replies the message back when it has finished.

The port doesn't need to be a normal port either where a message is sent back to. A message can be bounced back as a signal or even trigger a software interrupt as you've seen.

By “allocation overhead” I mean needing to allocate memory on the fly. So by comparison local variables are less overhead as they just get reserved on the stack and avoid an API call. I'm most likely just being pedantic as I would avoid any system calls allocating resources inside a debug routine. Given OS4 has the slab allocator it's probably not such a big deal.

Quote:
As i understand it, you still suggest to use for AllocSysObjectTags also ASOPORT_Signal when allocation for message, and this mean i can not create second reply port, and handle it without ? (sounds strange!) But what about “allocation overhead” which you mention, then if AllocSysObjectTags() still should be used for ?


Sorry, I see I've confused you. In this case you allocate a message. But it needs a reply port allocated as well. The reply port can just be specified as a signal using the ASOPORT_Signal tags as you have set up. But you will need to allocate a port with ASOT_PORT type and those tags.

However, since you are only messaging your own task, you can just skip the reply port all together. It can be set to zero in the message, in which case it will just mark the message as free when replied back. In this case, you can simply skip another port, and just signal back directly. When your main task has finished with the message just grab the process ID from the ProcessIDMessage and signal it back.

Quote:
The main()'s code is not changed, of course. Hope you wasn't mean that i need to change that too and fully rewrite it to handle new sort of signal without receiving a reply ?:)


It will need to bounce it back. You can use the ReplyMsg() mechanism which will need a port attached. Or just simply signal back with a SIGF_SINGLE in this case. That might be best in this case. It avoids setting up a port and you can just use a preset signal.

Quote:
And where is FreeSysObject() in your example ? Should't it be right after Wait(SIGF_SINGLE) ?


Oh yes it should. I just focussed on the message and waiting for signal to go ahead and continue.

Quote:
ps. Never touched anything with all this messages, but after reading wiki were under impression that for communicate between 2 tasks i need one single port , in which i do this communication by messages, not that i need different port for each messages which should be send from one task to another..


In the common case two ports will be involved. For source and destination. Source sends to destination, which then replies it back to source when finished.

So the simplest way if avoiding the reply port would be this:
IExec->DebugPrintF("port signal\n");
 
                while(
receivedMessage = (struct ProcessIDMessage *)IExec->GetMsg(mainPort))
                {
                    
IExec->DebugPrintF("mainport received: ProcessID = %lu\n"receivedMessage->processID);
                    
//IExec->ReplyMsg((struct Message *)receivedMessage);
                    
IExec->Signal((struct Task *)receivedMessage->processIDSIGF_SINGLE);
                }

Go to top
Re: Tracing
Home away from home
Home away from home


See User information
@Hypex
Quote:

So the simplest way if avoiding the reply port would be this:


Simple crashed right after i got "mainport received: ProcessID = 191" and code do "IExec->Signal((struct Task *)receivedMessage->processID, SIGF_SINGLE);".

I.e. processID messages from patched hook fine first time, we receive it, print the value, but then, when we need to answer we crash.

That how currently it looks like:

part from patched callhookpkt:

if (&process->pr_Task != NULL)
                        {
                                if (
hookstack != NULL)
                                {    
                                    
struct ProcessIDMessage *message = (struct ProcessIDMessage *)IExec->AllocSysObjectTags(ASOT_MESSAGE,
                                            
ASOMSG_Sizesizeof(struct ProcessIDMessage),
                                            
ASOPORT_AllocSigFALSE,
                                            
ASOPORT_SignalSIGB_SINGLE,
                                            
ASOMSG_ReplyPortNULL,
                                            
TAG_DONE);
                                            
                                    if (
message != NULL) {
                                            
message->processID process->pr_ProcessID// Get the process ID here
                                    
}
                                    
IExec->SetSignal(0SIGF_SINGLE);
                                    
IExec->PutMsg(mainPort, (struct Message *)message);
                                    
IExec->Wait(SIGF_SINGLE);
                                    
IExec->FreeSysObject(ASOT_MESSAGEmessage);
                                    
                                    
IExec->DebugPrintF("CallHookPkt call # %d\n"callhookspkt_counts++);
                                }
                        }
                }



Part from main():

if (signal portsig)
            {
                
IExec->DebugPrintF("port signal\n");
 
                while(
receivedMessage = (struct ProcessIDMessage *)IExec->GetMsg(mainPort))
                {
                    
IExec->DebugPrintF("mainport received: ProcessID = %lu\n"receivedMessage->processID);
                    
//IExec->ReplyMsg((struct Message *)receivedMessage);
                    
IExec->Signal((struct Task *)receivedMessage->processIDSIGF_SINGLE);
                }
            }

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: Tracing
Just can't stay away
Just can't stay away


See User information
@kas1e
Stop allocating anything in your patched function, your patch code is running in a foreign tasks and you don't know in which state it is.
Allocating anything, memory, ports, messages, etc., can for example break Forbid() since the memory, page, etc. allocator may have to wait for exclusive access with a mutex.

As long as you only want to debug a single task messages aren't required, sending signals is enough.
In the patch you can't allocate signals, for example fails if all are used already, use SIGF_SINGLE instead. For the main task you can allocate a signal.

Something like
patch function
patched_task IExec->FindTask(NULL);
IExec->SetSignal(0SIGF_SINGLE);
IExec->Signal(main_task<< portsig)
IExec->Wait(SIGF_SINGLE);

main()
if (signal portsig)
{
    
IExec->DebugPrintF("port signal for 0x%2508lx\n"patched_task);
    
stack traceetc.
    
IExec->Signal(patched_taskSIGF_SINGLE);
}

Go to top
Re: Tracing
Just can't stay away
Just can't stay away


See User information
@Hypex
Quote:
I noticed those VARARGSS68K but I didn't see why they were necessary. Any emulation of 68K var args is internally to the emulators so shouldn't need to be exposed.
Would have required 2 different implementations for all varagrs TagItem functions: One which can be called from PPC native code and a different one which can be called from emulated m68k code.

Quote:
Aside from that varargs are a common function practice in portable C code that can run on x86 or PPC and others so varargs never looked 68K exclusive to me.
The C parts are common, but the implementation of varargs is CPU specific.
IIRC on m68k everything is put on the stack, but on PPC the first 8 integer, FPU and AltiVec arguments are passed in registers and only if there are more the stack is used.
VARARGS68K doesn't use the standard PPC varagrs method but only the stack, exactly like on m68k, and a single function can be called form both PPC native and emulated m68k code.

Go to top
Re: Tracing
Home away from home
Home away from home


See User information
@joerg
I am completely looses now :( Aren't we tried to use messages/signals whatever for exactly purposes to send ProcessID from the patch to the main ? In your example, processID aren't transferred, which was the whole purpose of last 2 pages :)

Aren't with your example we simply return to globals again ? Because i had to define patched_task and main_task as globals out of the functions, and we then back to the same as before (process_to_inspect = process); with only one difference that we add signals for wait and send now around.

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: Tracing
Just can't stay away
Just can't stay away


See User information
@kas1e
Quote:
Aren't we tried to use messages/signals whatever for exactly purposes to send ProcessID from the patch to the main ? In your example, processID aren't transferred, which was the whole purpose of last 2 pages :)
Yes, but I don't understand why.
In your patch you are checking the task name or ProcessID and only do something for this single task. For a single task using signals is enough.
Sending messages with the ProcessID to the main task would only be required if you want to debug different tasks at the same time.

Go to top
Re: Tracing
Home away from home
Home away from home


See User information
@joerg
The problem was that for single invoking of CallHookPkt from my test binary, we have 150 CallHookPkts in the system. So, idea was to catch all those 150 CallHookPkts, and made a stack traces out of them all (to see, from where all they come).

So, if we will now just stacktrace my single task, we will have just one stack trace for my process. While need to have all stack traces for all CallHookPkts : with global set as before for 150 CallHookPkts i only have 12 stacktraces. All i want is to know from where each CallHookPkts come , all 150.

So i need something like - 1 CallHookPkt happens - 1 stack trace provides. For this purposes i probabaly must to do suspend/restart of tasks, but again, with globals and without messaging this wasn't enough (12 stack traces for 150 callhookpkts only).

Now trying to find a easy way to catch every callhookpkt (but only when my binary invoking) and made a stacktrace of any of them.

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: Tracing
Just can't stay away
Just can't stay away


See User information
@kas1e
Quote:
with global set as before for 150 CallHookPkts i only have 12 stacktraces
Because you didn't stop the patched task and wait until the main() task is done with the stack trace.
It can be done in different ways, sending messages, or SupendTask() in the patch and RestartTask() it in the main task after the stack trace is done, but using signals is the easiest way.

Quote:
So i need something like - 1 CallHookPkt happens - 1 stack trace provides.
Sending and waiting for signals does that.

Go to top
Re: Tracing
Home away from home
Home away from home


See User information
@joerg
Quote:

Sending and waiting for signals does that.


Right, so.. i doing that:

Out of functions at top:

uint32 portsig;
uint32 usersig;

struct Task *patched_task NULL;
struct Task *main_task NULL;

struct MsgPort *mainPort;


main():

main_task IExec->FindTask(NULL);
    
    
BOOL ABORT FALSE;
    
struct ProcessIDMessage *receivedMessage NULL;
    
    
mainPort IExec->AllocSysObjectTags(ASOT_PORTASOPORT_SignalSIGB_SINGLETAG_END);

    if(
mainPort != NULL)
    {
        
portsig 1U Wait(portsig usersig);

            if (
signal portsig)
            {
                
IExec->DebugPrintF("port signal\n");
 
                
/*while(receivedMessage = (struct ProcessIDMessage *)IExec->GetMsg(mainPort))
                {
                    IExec->DebugPrintF("mainport received: ProcessID = %lu\n", receivedMessage->processID);
                    //IExec->ReplyMsg((struct Message *)receivedMessage);
                    IExec->Signal((struct Task *)receivedMessage->processID, SIGF_SINGLE);
                }*/
                
                
IExec->DebugPrintF("port signal for 0x%08lx\n"patched_task);
                
//stack trace, etc.
                
IExec->Signal(patched_taskSIGF_SINGLE);
                
            }

            if (
signal usersig)
            {
                
IExec->DebugPrintF("ctrl+c signal\n");
                while(
receivedMessage = (struct ProcessIDMessage *)IExec->GetMsg(mainPort)) { // make sure port is empty
                    
IExec->ReplyMsg((struct Message *)receivedMessage);
                }    
                
ABORT TRUE;
            }
        }

    }


Patched CallHookPkt:

ULONG APICALL Patched_CallHookPkt(struct UtilityIFace *Selfstruct Hook *hookAPTR objectAPTR message) {

    
struct Process *process = (struct Process *)IExec->FindTask(NULL);

    if (
IS_PROCESS(process))
    {
        
struct CommandLineInterface *cli BADDR(process->pr_CLI);

        if(
cli)
        {            
            if(
cli->cli_Module)
            {
                static 
char buffer[128];
                
IDOS->CopyStringBSTRToC(cli->cli_CommandName,buffer,sizeof(buffer));
                
                if(!
stricmp(buffer,traced_binary)) 
                {
                        if (&
process->pr_Task != NULL)
                        {
                                if (
hookstack != NULL)
                                {
                                    
patched_task = &process->pr_Task;
                                    
                                    
IExec->DebugPrintF("set signal!\n");
                                    
IExec->SetSignal(0SIGF_SINGLE);
                                    
                                    
IExec->DebugPrintF("signal it!\n");
                                    
IExec->Signal(main_task1 Wait(SIGF_SINGLE);
                                    
                                    
IExec->DebugPrintF("CallHookPkt call # %d\n"callhookspkt_counts++);
                                }
                        }
                }

            }
        }
    } 


    return 
Original_CallHookPkt(Selfhookobjectmessage);
    
}
                                }


And on serial have that:
Quote:

set signal!
signal it!
now wait!


And nothing happens, like, i never come to the main task like "portsig" never sends. I tried to replace

Quote:

IExec->Signal(main_task, 1 << portsig);


on

Quote:

IExec->Signal(main_task, 1 << mainPort->mp_SigBit);


And it works as expected !

Then i printf out the values of portsig (which should be mainPort->mp_SigBit), and of mainPort->mp_SigBit exactly, and they different! :

Quote:

portsig = 0x00000010
mainPort->mp_SigBit = 0x00000004


WTF ? :) Shouldn't it be the same ?


Edited by kas1e on 2024/5/8 12:22:09
Edited by kas1e on 2024/5/8 12:23:17
Edited by kas1e on 2024/5/8 12:24:15
Edited by kas1e on 2024/5/8 12:26:25
Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: Tracing
Just can't stay away
Just can't stay away


See User information
@kas1e
You are mixing signal bit numbers with signal masks.

In the patch replace
IExec->Signal(&main_task->pr_Task<< portsig);
by
IExec->Signal(&main_task->pr_Taskportsig);


You could remove the unused port and message parts and simply use something like
int8 portbit IExec->AllocSignal(-1);
if (-
== portbiterror;
else 
portsig 1UL << portbit;
in main() to allocate a signal.

Quote:
portsig = 0x00000010
mainPort->mp_SigBit = 0x00000004


WTF ? :) Shouldn't it be the same ?
SigBit is the 8 bit signal bit number (0-31), portsig a 32 bit signal mask: 1 << SigBit;

Go to top

  Register To Post
« 1 2 3 (4) 5 6 »

 




Currently Active Users Viewing This Thread: 1 ( 0 members and 1 Anonymous Users )




Powered by XOOPS 2.0 © 2001-2024 The XOOPS Project