I am very puzzled, I can't seem to find utcb location in L4Ka::pistachio. One example do this:
L4_ThreadId_t mylocalid = L4_MyLocalId (); utcb_base = *(L4_Word_t *) &mylocalid; utcb_base &= ~(L4_UtcbAreaSize (kip) - 1);
where the current thread is initial thread (main), but i try this it do not work. Can someone suggest proper way to determine the utcb location so that I can create a new thread? Please
ok, I discover that the piece of code sort of work. The part of code that assigns new location to new thread seem to cause the problem. Now I solve that part this part of code do not work:
void func(void) { printf("thread start\n"); }
L4_MsgTag_t msg; L4_Clear(&msg); L4_Append(&msg,(L4_Word_t)func); L4_Append(&msg,(L4_word_t)stack); L4_Load(&msg); L4_Send(tid);
when i run the program it do not display "thread start", all other debugging messages show except this. can someone please help?
Why can not I see the message that suppose to be printed to the screen? Apparently the thread starts because the rest of initial thread do not continue. but the message is not printed.
I figure out what the problem is. I get an error e = 1 in the ErrorCode part of the utcb after send the ipc. What exactly do this mean? The only description the api manual give on this is "From is undefined in this case". What do this mean and how to correct it? Please help
here my code:
#include <l4io.h> #include <l4/thread.h> #include <l4/kip.h> #include <l4/schedule.h> #include <l4/ipc.h>
void Jenev(void) { L4_MsgTag_t tag; L4_ThreadId_t from; tag = L4_Wait (&from); printf("the thread was started\n"); }
int main() { printf("starting application [OK]\n"); L4_ThreadId_t me, jen; L4_Word_t baseNo, baseVer; L4_Word_t utcb_b, utcb_l; void * kip; L4_Word_t ip, sp; char stack[100]; kip = L4_KernelInterface(); L4_ThreadId_t mylocalid = L4_MyLocalId(); me = L4_MyGlobalId(); baseNo = L4_ThreadNo(me); baseVer = L4_Version(me); jen = L4_GlobalId(baseNo+1, baseVer); utcb_b = *(L4_Word_t*)&mylocalid; utcb_b &= ~(L4_UtcbAreaSize(kip) -1); utcb_l = utcb_b + (L4_UtcbSize(kip) * ((L4_ThreadNo(jen) - baseNo))); ip = (L4_Word_t)Jenev; sp = (L4_Word_t)stack; int res = L4_ThreadControl(jen, me, me, L4_nilthread, (void*)utcb_l); printf("starting jenev-thread "); if(!res) { printf("[FAIL]\n"); L4_Word_t err = L4_ErrorCode(); switch(err) { case 1: printf("no privilege\n"); break; case 2: printf("unavailale thread\n"); break; case 3: printf("invalid space\n"); break; case 4: printf("invalid scheduler\n"); break; case 6: printf("invalid UTCB location\n"); printf("root-thread number is: %d\n", (int)baseNo); printf("jenev-thread number is: %d\n", (int)L4_ThreadNo (jen)); printf("the utcb size is: %d \n", (int)L4_UtcbSize (kip)); printf("the additive is: %d\n", (int)(L4_UtcbSize(kip) * (L4_ThreadNo(jen) - baseNo))); break; case 8: printf("out of memory\n"); break; printf("the utcb location of root-thread is: %d \n", (int)utcb_b); printf("the utcb loaction of jenev-thread is: %d \n", (int)utcb_l); } } else printf("[OK]\n"); L4_Time_t snd_time_out = L4_TimePeriod(1000000); L4_Msg_t msg; L4_Clear(&msg); L4_Append(&msg, ip); L4_Append(&msg, sp); L4_Load(&msg); L4_MsgTag_t result = L4_Send(jen, snd_time_out); printf("initial thread continued\n"); if(L4_IpcFailed(result)) { L4_Word_t err = L4_ErrorCode(); printf("the ipc failed\n"); printf("error: [%d]\n", (int)err); } return 0; }
Hello Jason,
L4_Word_t ip, sp; char stack[100];
...
sp = (L4_Word_t)stack;
...
L4_Append(&msg, ip); L4_Append(&msg, sp); L4_Load(&msg); L4_MsgTag_t result = L4_Send(jen, snd_time_out);
I don't know if this is related to your problem but you should definitely specify the top (rather than the bottom) of the stack as initial stack pointer because the stack always grows from top to bottom. I recommend to use a larger stack anyway (just to be sure - printf might need more than 100 bytes of stack), would not place the new thread's stack as local variable on main's stack (better make it a static variable), and would use a machine-word-aligned stack size (even though x86 may tolerate an unaligned sp, other architectures do not).
Also, I warmly recommend you to give the Pistachio kernel debugger a try to inspect the state of the new created thread. You should also consider to not immediately return from the main function. The kernel will see roottask exiting, which is an unexpected behavior from the kernel's point of view. For a test, just insert an infinite loop at end of 'main'.
Cheers Norman
I take your advice but nothing change. I do not know what you mean by "use the top of the stack rather than the bottom" if i say "sp = (L4_Word_t)stack" would that mean the start address of the array? But just in case I use "sp = stack[1023]" My new code look like this:
#include <l4io.h> #include <l4/thread.h> #include <l4/kip.h> #include <l4/schedule.h> #include <l4/ipc.h>
char stack[1024];
void Jenev(void) { L4_MsgTag_t tag; L4_ThreadId_t from; tag = L4_Wait (&from); printf("the thread was started\n"); }
void main() { printf("starting application [OK]\n"); L4_ThreadId_t me, jen; L4_Word_t baseNo, baseVer; L4_Word_t utcb_b, utcb_l; void * kip; L4_Word_t ip, sp; kip = L4_KernelInterface(); L4_ThreadId_t mylocalid = L4_MyLocalId(); me = L4_MyGlobalId(); baseNo = L4_ThreadNo(me); baseVer = L4_Version(me); jen = L4_GlobalId(baseNo+1, baseVer); utcb_b = *(L4_Word_t*)&mylocalid; utcb_b &= ~(L4_UtcbAreaSize(kip) -1); utcb_l = utcb_b + (L4_UtcbSize(kip) * ((L4_ThreadNo(jen) - baseNo))); ip = (L4_Word_t)Jenev; sp = (L4_Word_t)stack; int res = L4_ThreadControl(jen, me, me, L4_nilthread, (void*)utcb_l); printf("starting jenev-thread "); if(!res) { printf("[FAIL]\n"); L4_Word_t err = L4_ErrorCode(); switch(err) { case 1: printf("no privilege\n"); break; case 2: printf("unavailale thread\n"); break; case 3: printf("invalid space\n"); break; case 4: printf("invalid scheduler\n"); break; case 6: printf("invalid UTCB location\n"); printf("root-thread number is: %d\n", (int)baseNo); printf("jenev-thread number is: %d\n", (int)L4_ThreadNo (jen)); printf("the utcb size is: %d \n", (int)L4_UtcbSize (kip)); printf("the additive is: %d\n", (int)(L4_UtcbSize(kip) * (L4_ThreadNo(jen) - baseNo))); break; case 8: printf("out of memory\n"); break; printf("the utcb location of root-thread is: %d \n", (int)utcb_b); printf("the utcb loaction of jenev-thread is: %d \n", (int)utcb_l); } } else printf("[OK]\n"); L4_Time_t snd_time_out = L4_TimePeriod(1000000); L4_Msg_t msg; L4_Clear(&msg); L4_Append(&msg, ip); L4_Append(&msg, sp); L4_Load(&msg); L4_MsgTag_t result = L4_Send(jen, snd_time_out); printf("initial thread continued\n"); if(L4_IpcFailed(result)) { L4_Word_t err = L4_ErrorCode(); printf("the ipc failed\n"); printf("error: [%d]\n", (int)err); } while(1) { printf("test loop\n") } }
Hello Jason,
On 04/01/2011 01:02 AM, Jason Philip wrote:
I take your advice but nothing change. I do not know what you mean by "use the top of the stack rather than the bottom" if i say "sp = (L4_Word_t)stack" would that mean the start address of the array? But just in case I use "sp = stack[1023]"
No, use 'sp = &stack[1024]'. This way, the initial sp points to the address just beyond the stack array. When the first stack element is pushed, the stack pointer gets pre-decremented and thus, the first element gets stored at offset '1024 - sizeof(L4_Word_t)'.
Please also remove the 'L4_Wait' call from your 'Jenev' function. There is no need to explicitly wait for the startup message. This message is implicitly handled by the kernel to start the execution of the new thread. As your code stands right now, the new thread would infinitely wait for a new message because no one is sending anything.
BTW, you could have figured this out by yourself with the help of the Pistachio kernel debugger. Please do not expect the subscribers of this mailing list to lend a helping hand for debugging your program if you are not willing to at least give the kernel debugger a serious try.
Good luck Norman
Hello Norman, I am new to l4ka and I do not know much about the debugger I try a few random option (q,t,s,p). 'q' give this:
showqueue
cpu 0: accounted tcb ROOTTASK, max_prio 255
[255]: (SIGMA0) ROOTTASK [100]: (000cc001) [000]: KRN_THRD) idle : IDLETHRD
't' give this:
showtcb tcb/tid/name [current]: current *** TCB: c0019000 *** ID: 000c8001 = bf000100/f014c000=== prio 255====== UIP: 00400011 queues: Rswl wait : NIL_THRD:NIL_THRD space: f014e000 USP: 00405040 tstate: RUNNING ready: ROOTTASK:ROOTTASK pdir : 0014b000 KSP: e0019790 sndhd : NIL_THRD send : NIL_THRD:NIL_THRD pager: SIGMA0 total quant: 0us, ts length : 10000us, curr ts 8282us abs timeout: 1018954us, rel timeout: - 215us sens prio: 255, delay: max=0us, curr=0us resources: 00000000 [] flags: 00000000 [ts] partner: 000cc001, saved partner: NIL_THRD, saved state: ABORTED , scheduler: ROOTASK
My new code look like this:
#include <l4io.h> #include <l4/thread.h> #include <l4/kip.h> #include <l4/schedule.h> #include <l4/ipc.h>
void Jenev(void) { printf("the thread was started\n"); while(1) { } }
int main() { printf("starting application [OK]\n"); L4_ThreadId_t me, jen; L4_Word_t baseNo, baseVer; L4_Word_t utcb_b, utcb_l; void * kip; L4_Word_t ip, sp; char stack[1024]; kip = L4_KernelInterface(); L4_ThreadId_t mylocalid = L4_MyLocalId(); me = L4_MyGlobalId(); baseNo = L4_ThreadNo(me); baseVer = L4_Version(me); jen = L4_GlobalId(baseNo+1, baseVer); utcb_b = *(L4_Word_t*)&mylocalid; utcb_b &= ~(L4_UtcbAreaSize(kip) -1); utcb_l = utcb_b + (L4_UtcbSize(kip) * ((L4_ThreadNo(jen) - baseNo))); ip = (L4_Word_t)Jenev; sp = (L4_Word_t)&stack[1024]; int res = L4_ThreadControl(jen, me, me, L4_nilthread, (void*)utcb_l); printf("starting jenev-thread "); if(!res) { printf("[FAIL]\n"); L4_Word_t err = L4_ErrorCode(); switch(err) { case 1: printf("no privilege\n"); break; case 2: printf("unavailale thread\n"); break; case 3: printf("invalid space\n"); break; case 4: printf("invalid scheduler\n"); break; case 6: printf("invalid UTCB location\n"); printf("root-thread number is: %d\n", (int)baseNo); printf("jenev-thread number is: %d\n", (int)L4_ThreadNo (jen)); printf("the utcb size is: %d \n", (int)L4_UtcbSize (kip)); printf("the additive is: %d\n", (int)(L4_UtcbSize(kip) * (L4_ThreadNo(jen) - baseNo))); break; case 8: printf("out of memory\n"); break; printf("the utcb location of root-thread is: %d \n", (int)utcb_b); printf("the utcb loaction of jenev-thread is: %d \n", (int)utcb_l); } } else printf("[OK]\n"); L4_Time_t snd_time_out = L4_TimePeriod(1000000); L4_Msg_t msg; L4_Clear(&msg); L4_Append(&msg, ip); L4_Append(&msg, sp); L4_Load(&msg); L4_MsgTag_t result = L4_Send(jen, snd_time_out); printf("initial thread continued\n"); if(L4_IpcFailed(result)) { L4_Word_t err = L4_ErrorCode(); printf("the ipc failed\n"); printf("error: [%d]\n", (int)err); } return 0; }
the problem is the pager is not assigned. The line:
L4_ThreadControl(jen,me,me,L4_nilthread,(void*)utcb_l);
should be
L4_ThreadControl(jen,me,me,me,(void*)utcb_l);
l4-hackers@os.inf.tu-dresden.de