Bits might not be so obvious, for some who has coded Javascript, or never learned anything about digital processing.
bits are in order: (highest) 31 to (lowest) 0, importent when want to shift bits right or left.
just like you have 1000's, 100's and 10's and 1's in the descimal system. it's place in binrary number thats set to active or 1, 0 is not active.
bit 5, 4, 3, 2, 1, 0
state off,off,off,off, On,off
bit 0, if 1 its on, 0 is off, if ON it has value 1 in decimal system bit 1, if 1 its on, 0 is off, if ON it has value 2 in decimal system bit 2, if 1 its on, 0 is off, if ON it has value 4 in decimal system bit 3, if 1 its on, 0 is off, if ON it has value 8 in decimal system bit 4, if 1 its on, 0 is off, if ON it has value 16 in decimal system bit 5, if 1 its on, 0 is off, if ON it has value 32 in decimal system
And so on.. the combination gives you any decimal number.
So when we taking about the signal it has value, bit it has also location in binrary number, this is the bit.
if more than one signal is set, then more than one bit is set, this is why you are geting a different value, when you’re reading the state of the task.
Edited by LiveForIt on 2024/5/8 17:20:15 Edited by LiveForIt on 2024/5/8 17:21:08 Edited by LiveForIt on 2024/5/8 18:36:53 Edited by LiveForIt on 2024/5/8 18:37:47 Edited by LiveForIt on 2024/5/8 18:38:13
(NutsAboutAmiga)
Basilisk II for AmigaOS4 AmigaInputAnywhere Excalibur and other tools and apps.
There is the output of all CallHookPkts with their stacktraces, when i just run simple hello world (no CallHookPkt calling from test case, just hello world via casual printf() from libc):
Almost no differences by amount of calls, +5-6 in case of CallHookPkt() test case.
And one more output i grab for 10 seconds when i do nothing few seconds, then clicking around by mouse, and collecting _all_ possible CallHookPkts() from system (and that include and processes, and tasks and whatever else FindTask() can find):
1). Everywhere i see [LIBS:locale.library] Offset: 0. Wtf ? Involved but not used ? Broken "offset" entry for stacktrace ?
2). As i can see, offsets in the kernel, dos, and elf.library practically the same always for each stack trace, mean it's some very commonly used functions , is there a way to get a picture of what ones ?
Then for sake of compare how many pure varargs CallHook() functions is used, i add patch for CallHook() too, and there just collect all the task/whatever FindTask(NULL) find in, and can say that when one run simple test binaries from shell, no CallHook() involved by system. But if i let's say spawn in console new tab gadgets, i have that:
So seems that at least CallHook() didn't used by system very often (a very little as far as i can see, but still).
Which is massively used, it's CallHookPkt() as expected, but what is unexpected, that OS4 have pure CallHook() in utility.library at all, and it wasn't very well documented everywhere, and more of it, before it was in amiga.lib in old times (so was a linker function) and now it still used in few bits of system, go figure why if almost everything is on CallHookPkt() already..
@Joerg Btw, when i tried to use the same "signal" method but for all the tasks/process in the CallHookPkt, i.e. just like this:
Then stacktrace massively overwrite other outputs (debugpritnf for name of task and amount of calls). Is it expected that it didn't work when different tasks involved, and not a single one like we did with signals ?
There is the output of all CallHookPkts with their stacktraces, when i just run simple hello world (no CallHookPkt calling from test case, just hello world via casual printf() from libc):
C library printf(), at least the newlib one, is no "problem", but the OS printf() like functions (IDOS->Printf(), IUtility->SNPrintf(), IExec->DebugPrintF(), etc.) are more or less all based on IExec->RawDoFmt() which is replaced (SetMethod()) by locale.library when it's started with (something similar to) ILocale->FormatString() which uses a Hook for the putCharFunc and you should get a CallHookPkt() call for each char.
Quote:
Then stacktrace massively overwrite other outputs (debugpritnf for name of task and amount of calls). Is it expected that it didn't work when different tasks involved, and not a single one like we did with signals ?
That's normal, debug output writes one char after another to the serial port, and if there are several tasks with debug output at the same time and task switches happen you get a mix of them. Maybe using something like
in the patch and Forbid()/Permit() around the stack trace DebugPrintF() could help. You still get a mix of different debug output, but at least complete lines for each task and not chars from different tasks in the same line.
Nah... use mutex instead, around debug printf, mutex should be forbid() free.. at least that was what we were told.
Using forbid has no advantage,
imagine a different task that print half a line without using forbid, now your task invokes forbid() and DebugPrintF, and Permit(), the other task, will continue after permit(), and the text will look bad.
perhaps patching DebugPrintF so it uses a mutex can do the trick, then the lock becomes global.
(NutsAboutAmiga)
Basilisk II for AmigaOS4 AmigaInputAnywhere Excalibur and other tools and apps.
Simple crashed right after i got "mainport received: ProcessID = 191" and code do "IExec->Signal((struct Task *)receivedMessage->processID, SIGF_SINGLE);".
Just realised why. I was going to test it myself before rereading this. The TaskID and ProcessID are different.
The TaskID isn't exactly an ID and is simply the Task pointer. But because AmigaOS shares lots of pointers it uses it as an ID. The ProcessID, which is a newer addition, actually assigns an ID to a process. Maybe they tried to clean it up and make it more like a modern OS that does use a process ID.
Somehow, although it's obvious now, I had missed that. You've got it working again now. But for fixing that one, your ProcessIDMessage object will need TaskID as well, which is simply the Task or Process pointer. I did notice your ProcessIDMessage only had ULONG and that explains it. Whoops.
if (message != NULL) {
message->processID = process->pr_ProcessID; // Get the process ID here
message->taskID = &process->pr_Task // Get the task ID here
}
C library printf(), at least the newlib one, is no "problem", but the OS printf() like functions (IDOS->Printf(), IUtility->SNPrintf(), IExec->DebugPrintF(), etc.) are more or less all based on IExec->RawDoFmt() which is replaced (SetMethod()) by locale.library when it's started with (something similar to) ILocale->FormatString() which uses a Hook for the putCharFunc and you should get a CallHookPkt() call for each char.
That explain all those "locale.library" string in the stack trace then, strange only why with offset:0 ?
Quote:
You still get a mix of different debug output, but at least complete lines for each task and not chars from different tasks in the same line.
Yep, that better, but still not very readable as it still mix of different debug output. If use messages with all those processIDs is it possible to deal with ?
@Hypex You only need struct Task *taskID in the message, processID can be get from that so it's redundant.
@kas1e Quote:
Yep, that better, but still not very readable as it still mix of different debug output. If use messages with all those processIDs is it possible to deal with ?
You could either add locking around the whole stack collecting part where you print things not just around a single printf but that would lock all other tasks until one stack trace is done. You could instead of printing it open a file for each task or each call (append taskId+timestamp to make unique file name) and print the trace there so you'd get a separate file for each call with just the stack trace for that call.
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.
Doesn't look portable and optimised for native code if it's forced to use a 68K compatible format. I suppose it's not too much overhead but did read somewhere that 68K varargs style or simply stacking data was incompatible to PPC.
Quote:
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.
68K and PPC are similar in that they allow for a number of registers. 68K has 15 in all it can use in total but PPC has only 8 GPR for all, so some fully registerised 68K functions are less efficient and stacked in PPC ABI. However, most varargs functions would stack most of the data, so on PPC it should all be stacked and pointed to in a register. Like 68K would do.
Quote:
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.
It would have to do some slight trick to embed in the stack frame I imagine. I recall something about an AmigaE PPC port said to be incompatible with E lists. Well, there are E compatible compilers, and they managed it. So it must be possible. E lists are similar to varargs. Simply a list of stacked items.
did read somewhere that 68K varargs style or simply stacking data was incompatible to PPC.
Alignment of the structs and on the stack is different: 2 bytes on m68k (even for 32 and 64 bit types), on PPC it's at least the size of the data type, for example 4 bytes for int32 and float, 8 bytes for int64 and double. For the AmigaOS structs that's changed with the #pragma pack(2) (GCC)/#pragma amiga-align (VBCC) at the start and and #pragma pack() (GCC)/#pragma default-align (VBCC) at the end of the OS includes to be m68k compatible.
Quote:
68K and PPC are similar in that they allow for a number of registers. 68K has 15 in all it can use in total but PPC has only 8 GPR for all,
PPC has 29 available GPR registers (+ r1 = stack pointer + r13 = small data pointer + r2 = baserel pointer = 32 total), m68k has 14 (+ a7 = stack pointer + a4 = small data pointer = 16 total, but 8 are for integers only and 6/8 only for pointers). IIRC the standard C ABI for m68k only uses 2-6 registers for argument passing depending on the data type of the arguments (d0 and d1 for 32 bit integers or d0+d1 for one 64 bit integer, a0 and a1 for pointers, fp0 and fp1 for float/double), on PPC 8-24 registers are used (8 GPR + 8 float/double + 8 vector).
Quote:
so some fully registerised 68K functions are less efficient and stacked in PPC ABI.
I don't see how that should be possible, neither in the standard C ABI, not when using REG(reg) arguments using more than the standard number of registers for arguments, nor with assembler.
Edited by joerg on 2024/5/10 18:33:33 Edited by joerg on 2024/5/10 18:34:48
For the AmigaOS structs that's changed with the #pragma pack(2) (GCC)/#pragma amiga-align (VBCC) at the start and and #pragma pack() (GCC)/#pragma default-align (VBCC) at the end of the OS includes to be m68k compatible.
Okay yes I've used that pragma pack myself when dealing with 68K structures on PPC code.
Quote:
PPC has 29 available GPR registers (+ r1 = stack pointer + r13 = small data pointer + r2 = baserel pointer = 32 total), m68k has 14 (+ a7 = stack pointer + a4 = small data pointer = 16 total, but 8 are for integers only and 6/8 only for pointers).
I updated my post but I see it wasn't clear. What I meant was on 68K the Amiga ABI, where ever it comes from, allows 15 parameters in registers for API functions. Made from address and data. On PPC, the SysV ABI only allows 8 parameters in GPRs, with any more needing to be stored in the stack frame. They could of course fit the rest in, but AFAIK, the OS4 ABI follows the standard.
Quote:
IIRC the standard C ABI for m68k only uses 2-6 registers for argument passing depending on the data type of the arguments (d0 and d1 for 32 bit integers or d0+d1 for one 64 bit integer, a0 and a1 for pointers, fp0 and fp1 for float/double), on PPC 8-24 registers are used (8 GPR + 8 float/double + 8 vector).
The traditional API only used standard registers AFAIK. I'm not ware of any 68K APIs using FPU registers. Even math ones would have hid any FPU use and only accepted integers unless there are specific ones I'm unaware of. So for PPC it can support FPU as well as vector. But that would need OS4 specific API in that case. There is pointers to FPU data in tag lists but it's not in registers.
Quote:
I don't see how that should be possible, neither in the standard C ABI, not when using REG(reg) arguments using more than the standard number of registers for arguments, nor with assembler.
I'll give an example. BltBitMap(). It takes over 8 parameters so on PPC would be split. In the usual case. I thought there was some function that used all registers possible but cannot see it. Don't get any answers online.
Perhaps the fact that doubles, floats are passed on stack, can make it easier to use the same API for A1222 and any other PowerPC computers. having to store it in register, just makes it harder.
(NutsAboutAmiga)
Basilisk II for AmigaOS4 AmigaInputAnywhere Excalibur and other tools and apps.
Well, the ABI does allow for floats to be passed. And it is efficient to use registers since it needs to be calculated in FPRs. But AmigaOS doesn't traditionally pass floats in library functions. As well as the A1222 having non standard FPU. The taglist is restricted to 32 bit words and has been criticised for being unable so support 64 bit types directly. It is however designed to be key/value system with pointers. Tags do have flags so they could be extended but that would involve extending to 64 bits, either to mixed or 64 only. Tags have flags lol.
@joerg Talked with some os3/os4 devs, to find out, that back in 1990, in the internal times of creating v36-38 , they firstly create callhookpkt() for user based callbacks. Then, after some months, were created independently callhook() and its callhookA(). While, all what they need is to create CallHookPktA() stub and that all.
So question which noone were able to answer me: why there were needs to create callhook() at all in amiga.lib, when, intuition has already callhookpkt, and all ut needs is callhookpktA(), and be done with it.
Amiga.lib ones were faster ? Less code ? But then it lioks like more code instead (put stuff on stack, back, etc). I can understand if CallHookPkt() were created after, for exactly avoiding of more code, but by history commits of the os3 it looks exactly in opposite: first one they create callhookpkt, and then after few months, internaly, they create callhook/callhooka in amiga.lib, like, it need them more. For end user it was a single push release of all 3: callhookpkt in utility, and callhook/callhooka in amiga.lib
What was the logic behind of such reversed and doubled work ?
On os4 this another story: callhookpkt were choicen, expanded to have emulator check, and callhook() added for easy porting from os3 (which developers back in past by some reasson prefer callhook from amiga.lib doing job). Probably it worth of bugreport to ditch few remain callhook() in os4 components in favor of callhookpkt(). Those 16 assembler instructions on emulator check cant bring any real overhead probably ?
So question which noone were able to answer me: why there were needs to create callhook() at all in amiga.lib, when, intuition has already callhookpkt, and all ut needs is callhookpktA(), and be done with it.
CallHookPkt() was added in utility.library V36 (AmigaOS 2.0), using the libamiga.a CallHook() instead was required for software which should work on AmigaOS 1.x as well.
CallHookPkt() was added in utility.library V36 (AmigaOS 2.0), using the libamiga.a CallHook() instead was required for software which should work on AmigaOS 1.x as well.
That is strange, because as far as i know, there wasn't any callhook/callhookpkt until V36.8 (i.e. till amigaos 1.4 there wasn't any user-possible-used callhook() or callhookpkt() ). Even more, the single mention of first hooks in internal os3 code (checked by os3 developers), is dated by alpha 15 of amigaos2.0, with only internal use for utility.library. Only starting from beta1 of amigaos2.0 there were introduced callhookpkt(), and then a bit later were introduced callhook()/callhooka() in amiga.lib.
In other words, there wasn't any reasons to support 1.x code, as there wasn't any hooks at 1.4 times. It was a fresh addition from scratch. There should be some other reasons why they make 2 different functions doing the same, but called different and one placed in utility.library and another in amiga.lib (and the later on is surely worse, as take more stack space, right? )
In other words, there wasn't any reasons to support 1.x code, as there wasn't any hooks at 1.4 times.
After AmigaOS 2.0 was released for at least 5 years, maybe even longer, most AmigaOS software was still built to work on AmigaOS 1.x as well. Even if there are no Hooks in AmigaOS 1.x itself user code of that time built for both AmigaOS 1.x and 2.x probably used them internally, for example in functions used on AmigaOS 1.x only adding support/replacements for new AmigaOS 2.x features, as well as in the AmigaOS 2.x parts.
Except for AmigaOS 1.x support there is no reason at all to have a CallHook[A]() function in amiga.lib since CallHookPkt() is available in the AmigaOS 2.0+ utility.library.
@joerg I was told that the first hook (Even wasn't called callhook, but some older initial version) was the one which is used internally in the utility.library, for the string gadget. And it was in Alpha 15 of AOS2 (~1.4 somewhere in ks 35.xx). Prior to that, there wasn't any hooks usage inside the amigaos at all (in any function). I.e., no amigaos prior 1.4 have inside internally any hooking functionality of any sort, just direct usage of function and pointers, etc. By date it was in 8 june 1989. So it was first time of first hook internal (!) usage in utility.library, not even user-allowed code was. And it was Alpha of amigaos2 (So wasn't released anything prior with giving hooking functionality).
Then after 6 months, in the same "internal" code changes, in the beta1 of amigaos2.0, they made CallHookPkt(). So, fresh function, all fine, nothing released to anyone (except maybe this "beta of os2, named 1.4 for a3000). And then, in amiga.lib v37 (i do not know date exactly, and dunno what ks it was with it), then created CallHook/A in.
Taking into account that internally only utility.library use it (and when it use it, it wasn't called callhook, but just some internal name) , and that they have utility.library with callhookpkt already, i fail to see why they create CallHook/A.
I mean, it didn't looks like for support OS1.x, because not internally, not externaly hooking vere done for OS1.x. Maybe issues was all this C compilers (and maybe assembler ones?) asking for things to be on stack, so to make live of assembler programmers easy or something ? There should be another reasson, i just want to understand what one :) To fully fill the whole historical picture in OS3, before further annoying everyone about OS4 :))
NOTES
This function first appeared in the V37 release of amiga.lib.
However, it does not depend on any particular version of the OS,
and works fine even in V34.
Quote:
Maybe issues was all this C compilers (and maybe assembler ones?) asking for things to be on stack, so to make live of assembler programmers easy or something ?
amiga.lib CallHook() is a varargs function using the stack (on m68k) for the message, utility.library CallHookPkt() uses registers with a pointer to the message, similar to TagItem functions (always two versions, one with a pointer to a TagItem array in a register, one using varargs on the stack instead).
However, that doesn't explain why amiga.lib has CallHookA() as well, which is identical to utility.library CallHookPkt() (except for maybe utility.library using 3 registers for the arguments, amiga.lib using 3 arguments on the stack instead, not sure). The reason for CallHookA() in amiga.lib can only be AmigaOS 1.x compatibility, as written in the NOTES of the autodoc.
The reason for CallHookA() in amiga.lib can only be AmigaOS 1.x compatibility, as written in the NOTES of the autodoc.
Very strange.. If that of course were true that AmigaOS1.x have no single hooks usage not internally not externally (just for a little time , for 6 months, of internal coding)..
From another side, maybe at this time, when assembler were too popular in amiga coding, they think that if one use amiga.lib , and it's vararg based CallHook(), then, if developers want non vararg based, then he should't have the needs to open utility.library (some additional code), and use CallHookPkt(), while, he can just use CallHookA() from amiga.lib at the same time.
But then, it didn't explain why then utility.library have only CallHookPkt() and didn't have CallHook_varargs() or similiar to amiga.lib's CallHook() or something so to fill the logic gap :)
But maybe i were falsely informed, and utility.library wasn't the only and single one using hooks internaly and there were released with them for public, before CallHookA() and CallHook() were implemented in amiga.lib
I was told that it was like this:
Alpha 5 of AmigaOS 2.0 (known as AmigaOS 1.4) in 8 June 1989 introduce iHook and CHook(). And 1.4 it is V35 (not V34). So the first (and even named different) hooking functionality were added to intuition.
How it is possible that in amiga.lib autodic, they wrote about support of "v34"... Like this is all wrong about first introduce of iHook and CHook() ?
Then, i was told that right after 6 months, after Alpha 5, in the Beta 1 of AmigaOS 2.0 in Kickstart 36.8 introduce CallHookPkt() , in 22 December 1989.
Then in amiga.lib with Kickstart v37 they introduce CallHook() and CallHookA(). But what data exactly, what exactly subversionof kickstart : dunno.
There seems some bug in the dates then, if amiga.lib told that "all should work with V34" , which is amigaos 1.3 , and not 1.4 where first hooks were introduced (seems not, then?)
PS. Also, did i understand it correctly, that they (os4 devs) tried to get rid of Varargs functions mostly from API ? Why i ask about, is that they say there https://wiki.amigaos.net/wiki/Linker_Libraries , that:
Intuition
CallHook() and CallHookA()
These functions invoke hooks. CallHook() expects a parameter packet ("message") on the stack, while CallHookA() takes a pointer to the message.
Replaced by IUtility->CallHookPkt() in V50.
Like, both were deprecated in favor of single CallHookPkt() , so to not have varargs function. Even if they have CallHook() still in utility.library (probably side effect of easy porting from os3 back in times), it all looks like that they want to get rid of Varargs one. Maybe because Varargs ones is potetialy not safe-ones, as can corrupt the stack in some conditions , etc, and that is the reassons they want non-varargs one to be used always ?