Hi,
I'm using the following example provided by Michael Hohmuth in 2000 to create new tasks and threads: http://os.inf.tu-dresden.de/pipermail/l4-hackers/2000/000384.html
I've placed the code in a copy of the hello example, but added
REQUIRES_LIBS = l4sys
to the Makefile. The directory structure is located at './l4/pkg/taskcreat'.
Nevertheless, compilation is terminated due to a fatal error:
./l4/pkg/taskcreat/server/src/main.c:5:29: fatal error:
l4/sys/syscalls.h: No such file or directory
Why is syscalls.h missing here?
Best regards, Valentin
Is it usually generated?
Sent from my iPhone
On Aug 19, 2014, at 5:20 AM, Valentin Hauner valentinhauner@gmx.de wrote:
Hi,
I'm using the following example provided by Michael Hohmuth in 2000 to create new tasks and threads: http://os.inf.tu-dresden.de/pipermail/l4-hackers/2000/000384.html
I've placed the code in a copy of the hello example, but added
REQUIRES_LIBS = l4sys
to the Makefile. The directory structure is located at './l4/pkg/taskcreat'.
Nevertheless, compilation is terminated due to a fatal error:
./l4/pkg/taskcreat/server/src/main.c:5:29: fatal error:
l4/sys/syscalls.h: No such file or directory
Why is syscalls.h missing here?
Best regards, Valentin
l4-hackers mailing list l4-hackers@os.inf.tu-dresden.de http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
Hi,
I'm doing a 'make O=/path/to/l4re-builddir' in that directory where the file main.c is located. Or what do you mean by usually generated?
Best regards, Valentin
On 08/19/2014 02:34 PM, David Leimbach wrote:
Is it usually generated?
Sent from my iPhone
On Aug 19, 2014, at 5:20 AM, Valentin Hauner valentinhauner@gmx.de wrote:
Hi,
I'm using the following example provided by Michael Hohmuth in 2000 to create new tasks and threads: http://os.inf.tu-dresden.de/pipermail/l4-hackers/2000/000384.html
I've placed the code in a copy of the hello example, but added
REQUIRES_LIBS = l4sys
to the Makefile. The directory structure is located at './l4/pkg/taskcreat'.
Nevertheless, compilation is terminated due to a fatal error:
./l4/pkg/taskcreat/server/src/main.c:5:29: fatal error:
l4/sys/syscalls.h: No such file or directory
Why is syscalls.h missing here?
Best regards, Valentin
l4-hackers mailing list l4-hackers@os.inf.tu-dresden.de http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
I haven't looked in a while to be honest but many platforms generate their syscalls.h files. I'm wondering if the build time dependencies to generate it are working properly if that's why it is missing.
Sent from my iPhone
On Aug 19, 2014, at 5:39 AM, Valentin Hauner valentinhauner@gmx.de wrote:
Hi,
I'm doing a 'make O=/path/to/l4re-builddir' in that directory where the file main.c is located. Or what do you mean by usually generated?
Best regards, Valentin
On 08/19/2014 02:34 PM, David Leimbach wrote: Is it usually generated?
Sent from my iPhone
On Aug 19, 2014, at 5:20 AM, Valentin Hauner valentinhauner@gmx.de wrote:
Hi,
I'm using the following example provided by Michael Hohmuth in 2000 to create new tasks and threads: http://os.inf.tu-dresden.de/pipermail/l4-hackers/2000/000384.html
I've placed the code in a copy of the hello example, but added
REQUIRES_LIBS = l4sys
to the Makefile. The directory structure is located at './l4/pkg/taskcreat'.
Nevertheless, compilation is terminated due to a fatal error:
./l4/pkg/taskcreat/server/src/main.c:5:29: fatal error:
l4/sys/syscalls.h: No such file or directory
Why is syscalls.h missing here?
Best regards, Valentin
l4-hackers mailing list l4-hackers@os.inf.tu-dresden.de http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Hi,
I'm using the following example provided by Michael Hohmuth in 2000 to create new tasks and threads: http://os.inf.tu-dresden.de/pipermail/l4-hackers/2000/000384.html
this example was for a previous version of our system (L4Env). Do not use it for writing L4Re programs.
For L4Re, you have two options:
1) Use libpthread as in pkg/examples/libs/pthread.
2) Use Fiasco's thread primitives. For examples using this, you might want to grep for l4_thread_control in pkg/examples. There are a couple of examples using this.
Bjoern
Hi,
On 08/19/2014 02:55 PM, Björn Döbel wrote:
- Use Fiasco's thread primitives. For examples using this, you might want to grep for l4_thread_control in pkg/examples. There are a couple of examples using this.
That worked, I used ex_utcb_ipc as a basis (located in ./l4/pkg/examples/sys/utcb-ipc) and modified it. I replaced the read/write operations in functions 'thread1' and 'thread2' with some simple test output with printf. However, after seeing the outputs 'Thread1 up' and 'Thread2 up', I'm getting the following errors:
L4Re[rm]: unhandled read page fault @18 pc=101d244 L4Re: unhandled exception: pc=0x101d244
These errors disappear by substituting 'l4re_env()->rm' in the thread control section of main.c with 'l4re_env()->main_thread', but then I don't get a 'Thread2 up' (logically).
In another example that's very similiar to the above one, I'm getting these errors (with different 'pc'):
L4Re[rm]: unhandled read page fault @0 pc=0 L4Re: unhandled exception: pc=0x0
pc seems to stand for program counter, but how can I debug effectively here?
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 20.08.2014 19:06, Valentin Hauner wrote:
Hi,
On 08/19/2014 02:55 PM, Björn Döbel wrote:
- Use Fiasco's thread primitives. For examples using this, you
might want to grep for l4_thread_control in pkg/examples. There are a couple of examples using this.
That worked, I used ex_utcb_ipc as a basis (located in ./l4/pkg/examples/sys/utcb-ipc) and modified it. I replaced the read/write operations in functions 'thread1' and 'thread2' with some simple test output with printf. However, after seeing the outputs 'Thread1 up' and 'Thread2 up', I'm getting the following errors:
L4Re[rm]: unhandled read page fault @18 pc=101d244 L4Re: unhandled exception: pc=0x101d244
These errors disappear by substituting 'l4re_env()->rm' in the thread control section of main.c with 'l4re_env()->main_thread', but then I don't get a 'Thread2 up' (logically).
In another example that's very similiar to the above one, I'm getting these errors (with different 'pc'):
L4Re[rm]: unhandled read page fault @0 pc=0 L4Re: unhandled exception: pc=0x0
pc seems to stand for program counter, but how can I debug effectively here?
Right. The page fault message tells you the instruction pointer and the page-faulting address. What I usually do in the first case (PC=<some value not NULL>) is I try to figure out where in the program this is using objdump. (If you are testing in Qemu, you might even try attaching with GDB.)
In the second case (PC == 0) that won't work. This looks like someone already performed a jmp/call to address 0. Here you will have to figure out where things go wrong using printf()s. (Or GDB in the qemu scenario...)
Does that help?
Bjoern
Hi,
On 08/20/2014 07:53 PM, Björn Döbel wrote:
In the second case (PC == 0) that won't work. This looks like someone already performed a jmp/call to address 0. Here you will have to figure out where things go wrong using printf()s. (Or GDB in the qemu scenario...)
Does that help?
Yes, a bit. I decided to debug it with jdb. I've attached the jdb output as well as the main.c with the source code. It's a very small and simple example. The function 'create_edf_thread' matches largely with the main function of your utcb-ipc example, it just sets a different scheduling parameter (deadline based).
Concerning the thread list output, those with id's 25 and 26 are the ones executing the functions thread1() respectively thread2() in main.c. I'm not sure what the state 'exc_progr' means for them in this context. 1b is #threadipc itself, 1e seems to be the main thread of it (but I'm not sure of that).
Does your trained eye see the cause of this error?
Best regards, Valentin
On Thu Aug 21, 2014 at 16:18:46 +0200, Valentin Hauner wrote:
On 08/20/2014 07:53 PM, Björn Döbel wrote:
In the second case (PC == 0) that won't work. This looks like someone already performed a jmp/call to address 0. Here you will have to figure out where things go wrong using printf()s. (Or GDB in the qemu scenario...)
Does that help?
Yes, a bit. I decided to debug it with jdb. I've attached the jdb output as well as the main.c with the source code. It's a very small and simple example. The function 'create_edf_thread' matches largely with the main function of your utcb-ipc example, it just sets a different scheduling parameter (deadline based).
Concerning the thread list output, those with id's 25 and 26 are the ones executing the functions thread1() respectively thread2() in main.c. I'm not sure what the state 'exc_progr' means for them in this context. 1b is #threadipc itself, 1e seems to be the main thread of it (but I'm not sure of that).
Does your trained eye see the cause of this error?
The main issue is that you start 2 threads and then immediately leave the main function, which exits your program and would also destroy all threads. But it does not get so far...
static int create_edf_thread(void *func, unsigned deadline) { thread_stacks[count] = malloc(8 << 10);
l4_msgtag_t tag; l4_cap_idx_t thread_cap = l4re_util_cap_alloc();
if (l4_is_invalid_cap(thread_cap)) return -1;
tag = l4_factory_create_thread(l4re_env()->factory, thread_cap); if (l4_error(tag)) return -1;
l4_thread_control_start(); l4_thread_control_pager(l4re_env()->rm); l4_thread_control_exc_handler(l4re_env()->rm); l4_thread_control_bind((l4_utcb_t *)l4re_env()->first_free_utcb, L4RE_THIS_TASK_CAP);
Each thread needs to have a unique UTCB. In this example, you could fix it like this: l4re_env()->first_free_utcb = (l4_addr_t)l4re_env()->first_free_utcb + L4_UTCB_OFFSET; Remember that the size of the initial UTCB area is limited, so this only works a few times (allocating more is possible).
As both threads use the same UTCB this could result in the behavior you're seeing.
tag = l4_thread_control_commit(thread_cap); if (l4_error(tag)) return -2;
tag = l4_thread_ex_regs(thread_cap, (l4_umword_t)func, (l4_umword_t)(thread_stacks[count] + sizeof(thread_stacks[count])), 0); if (l4_error(tag)) return -3;
l4_sched_param_t sp = l4_sched_param_by_type(Deadline, deadline, 0); tag = l4_scheduler_run_thread(l4re_env()->scheduler, thread_cap, &sp); if (l4_error(tag)) return -4;
thread_caps[count] = thread_cap;
return count++; }
int main(void) { create_edf_thread(thread1, 1); create_edf_thread(thread2, 3);
Just calling thread() here should also work.
Adam
Hi,
thanks for your reply.
On 08/21/2014 11:49 PM, Adam Lackorzynski wrote:
The main issue is that you start 2 threads and then immediately leave the main function, which exits your program and would also destroy all threads. But it does not get so far...
Each thread needs to have a unique UTCB. In this example, you could fix it like this: l4re_env()->first_free_utcb = (l4_addr_t)l4re_env()->first_free_utcb + L4_UTCB_OFFSET; Remember that the size of the initial UTCB area is limited, so this only works a few times (allocating more is possible).
As both threads use the same UTCB this could result in the behavior you're seeing.
I've tried both of your suggestions, but none of them solved the problem. Then I've added
l4re_util_cap_free_um(thread_caps[x]);
at the end of each thread function and now the exception does not appear any more. All output ("Hello World ...") is produced as supposed to be.
I've attached the modified source file for your convenience. Note that the idling of the main thread (lines 109 f.) as well as the manipulation of first_free_utcb (line 99) are _commented out_.
Obviously, both created threads can go on although the main thread has already ended? Why? Is it right that the manipulation of first_free_utcb is necessary only when there is any IPC? In my example, none of the threads is communicating via the message registers.
Best regards, Valentin
On Sat Aug 23, 2014 at 15:12:01 +0200, Valentin Hauner wrote:
On 08/21/2014 11:49 PM, Adam Lackorzynski wrote:
The main issue is that you start 2 threads and then immediately leave the main function, which exits your program and would also destroy all threads. But it does not get so far...
Each thread needs to have a unique UTCB. In this example, you could fix it like this: l4re_env()->first_free_utcb = (l4_addr_t)l4re_env()->first_free_utcb + L4_UTCB_OFFSET; Remember that the size of the initial UTCB area is limited, so this only works a few times (allocating more is possible).
As both threads use the same UTCB this could result in the behavior you're seeing.
I've tried both of your suggestions, but none of them solved the problem. Then I've added
l4re_util_cap_free_um(thread_caps[x]);
at the end of each thread function and now the exception does not appear any more. All output ("Hello World ...") is produced as supposed to be.
I've attached the modified source file for your convenience. Note that the idling of the main thread (lines 109 f.) as well as the manipulation of first_free_utcb (line 99) are _commented out_.
Obviously, both created threads can go on although the main thread has already ended? Why? Is it right that the manipulation of first_free_utcb is necessary only when there is any IPC? In my example, none of the threads is communicating via the message registers.
The threads are doing printf which does an IPC implicitly. What happens is that first thread runs to its end and then the second runs, so they do not overlap during their runtime. It is just too short and they're not sleeping between the printfs. I've tried you example and it works as I think it should work (omitting the Deadline parameter). Immediate exit with no waiting in main() and with waiting 2 times 10 lines of each thread. I suggest that you first make sure you program behaves like it should with the default scheduler, and only then change over to your scheduler.
Adam
Hi,
On 08/24/2014 11:27 PM, Adam Lackorzynski wrote:
I suggest that you first make sure you program behaves like it should with the default scheduler, and only then change over to your scheduler.
Thanks, that's a good idea.
Is there a simple way to set the name of the threads displayed in the JDB thread list from the L4Re system? I'm still creating my threads as described in my mail from August 23th and want to pass individual thread names to Fiasco. I've found a function named l4_debugger_set_object_name (e.g. moe is using it), but using it had no effect.
Secondly, I've attached the modified l4_scheduler_run_thread_u function residing in ./l4/pkg/l4sys/include/scheduler.h. I've added an attribute named deadline to l4_sched_param_t and pass it via message register #5 to Fiasco. Initially, the second argument of the message tag for l4_ipc_call was set to 5 (5 registers to transfer), now I've set it to 6. Everything works, but I wonder where the information _which_ thread to run is passed to Fiasco? Message register #7 (previous: #6) contains information about the thread object, but it is not passed to Fiasco?
Best regards, Valentin
On Thu Aug 28, 2014 at 10:18:11 +0200, Valentin Hauner wrote:
Hi,
On 08/24/2014 11:27 PM, Adam Lackorzynski wrote:
I suggest that you first make sure you program behaves like it should with the default scheduler, and only then change over to your scheduler.
Thanks, that's a good idea.
Is there a simple way to set the name of the threads displayed in the JDB thread list from the L4Re system? I'm still creating my threads as described in my mail from August 23th and want to pass individual thread names to Fiasco. I've found a function named l4_debugger_set_object_name (e.g. moe is using it), but using it had no effect.
l4_debugger_set_object_name() is the function to use. Tried checking the return value?
Secondly, I've attached the modified l4_scheduler_run_thread_u function residing in ./l4/pkg/l4sys/include/scheduler.h. I've added an attribute named deadline to l4_sched_param_t and pass it via message register #5 to Fiasco. Initially, the second argument of the message tag for l4_ipc_call was set to 5 (5 registers to transfer), now I've set it to 6. Everything works, but I wonder where the information _which_ thread to run is passed to Fiasco? Message register #7 (previous: #6) contains information about the thread object, but it is not passed to Fiasco?
It is. It's the third parameter of the l4_msgtag (the 1) indicating this.
Adam
Hi,
On 09/01/2014 12:02 AM, Adam Lackorzynski wrote:
l4_debugger_set_object_name() is the function to use. Tried checking the return value?
Thanks, it's working now. I've misplaced the call of that function before.
I'm currently struggling with creating a new task. I guess, according to the initial post of this mailing list thread, using the following interface is deprecated? https://os.inf.tu-dresden.de/L4/l4libman/l4_task_new.html
So I've found l4_factory_create_task in factory.h. Unfortunately, there seems to be no example in ./l4/pkg how to use it. My first try is the following:
l4_cap_idx_t task_cap = l4re_util_cap_alloc(); l4_fpage_t task_fpage = l4_fpage(l4re_env()->first_free_utcb, 1024,
L4_CAP_FPAGE_RW);
l4_factory_create_task(l4re_env()->factory, task_cap, task_fpage); // Create thread, start thread control sequence ... l4_thread_control_bind((l4_utcb_t *)l4re_env()->first_free_utcb, task_cap); // Commit & shift first_free_utcb ...
But when executing the example, the states of all threads created are set to 'dead'. I'm not sure about using first_free_utcb as start address for the flex-page as it is used as a offset for threads' UTCBs normally.
Can you give a small working example for creating new tasks? Basically, I want to create a new task for each thread demanded by my end users. So the number of tasks and threads to create is variable.
Thanks!
Best regards, Valentin Hauner
On Mon Sep 01, 2014 at 18:31:40 +0200, Valentin Hauner wrote:
On 09/01/2014 12:02 AM, Adam Lackorzynski wrote: I'm currently struggling with creating a new task. I guess, according to the initial post of this mailing list thread, using the following interface is deprecated? https://os.inf.tu-dresden.de/L4/l4libman/l4_task_new.html
It belongs to a previous and now incompatible version of L4. It won't work anymore.
So I've found l4_factory_create_task in factory.h. Unfortunately, there seems to be no example in ./l4/pkg how to use it.
Most use the C++ interface, so looking for 'create_task' is better.
My first try is the following:
l4_cap_idx_t task_cap = l4re_util_cap_alloc(); l4_fpage_t task_fpage = l4_fpage(l4re_env()->first_free_utcb, 1024,
L4_CAP_FPAGE_RW);
l4_factory_create_task(l4re_env()->factory, task_cap, task_fpage); // Create thread, start thread control sequence ... l4_thread_control_bind((l4_utcb_t *)l4re_env()->first_free_utcb, task_cap); // Commit & shift first_free_utcb ...
But when executing the example, the states of all threads created are set to 'dead'. I'm not sure about using first_free_utcb as start address for the flex-page as it is used as a offset for threads' UTCBs normally.
When creating a new task you're free to put the UTCB area anywhere in the task's address space. Also, the size argument of l4_fpage is the size in log2, so maybe 12 is a good number (the minimum because it's a page). Of course you can use the same address range for the new task, so using l4re_env()->first_free_utcb is ok (lower bits are truncated by l4_fpage, so just using it is ok).
Can you give a small working example for creating new tasks? Basically, I want to create a new task for each thread demanded by my end users. So the number of tasks and threads to create is variable.
examples/sys/vcpu/vcpu.cc creates a task, however does not directly put a thread in there, you have to adapt that part a bit. Why not use ned for creating tasks?
Adam
Hi,
On 09/02/2014 12:27 AM, Adam Lackorzynski wrote:
Most use the C++ interface, so looking for 'create_task' is better. Why not use ned for creating tasks?
My whole EDF library is written in C now, so switching to C++ or Lua makes it very uncomfortable for me.
On 09/02/2014 12:27 AM, Adam Lackorzynski wrote:
Also, the size argument of l4_fpage is the size in log2, so maybe 12 is a good number (the minimum because it's a page).
Thanks, that part is working now. The new tasks are created properly and displayed as 'ready' in the JDB thread list.
But there's another problem: Using the region mapper of the current task does not work for the newly created tasks, of course. I've attached a small example that illustrates the problem (task creation: lines 19-25, setting pager and exception handler: lines 40-48). I've tried to make it as small as possible for your convenience.
How can I create a dedicated region mapper for each of the new tasks? Or is it better to just map the old region mapper to the new tasks? I've found
l4_task_map(task_cap, L4RE_THIS_TASK_CAP, ... )
but I didn't come along with the third and fourth parameter.
Best regards, Valentin
On Tue Sep 02, 2014 at 11:19:35 +0200, Valentin Hauner wrote:
Hi,
On 09/02/2014 12:27 AM, Adam Lackorzynski wrote:
Most use the C++ interface, so looking for 'create_task' is better. Why not use ned for creating tasks?
My whole EDF library is written in C now, so switching to C++ or Lua makes it very uncomfortable for me.
No problem. There are both C and C++ variants of each function so you can also look at C++ code to see how things are arranged and use C in your code.
On 09/02/2014 12:27 AM, Adam Lackorzynski wrote:
Also, the size argument of l4_fpage is the size in log2, so maybe 12 is a good number (the minimum because it's a page).
Thanks, that part is working now. The new tasks are created properly and displayed as 'ready' in the JDB thread list.
But there's another problem: Using the region mapper of the current task does not work for the newly created tasks, of course. I've attached a small example that illustrates the problem (task creation: lines 19-25, setting pager and exception handler: lines 40-48). I've tried to make it as small as possible for your convenience.
How can I create a dedicated region mapper for each of the new tasks? Or is it better to just map the old region mapper to the new tasks? I've found
l4_task_map(task_cap, L4RE_THIS_TASK_CAP, ... )
but I didn't come along with the third and fourth parameter.
Generally, you cannot just use the RM of your program for the new task. Your RM knows how to page your program but not the task you created. However, you're not actually starting a new program but rather just start a new thread in a new task from within the same binary. So your RM can page both.
And indeed, you need to map the cap to the new task.
l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_obj_fpage(l4re_env()->rm, 0, L4_FPAGE_RO), l4_map_obj_control(l4re_env()->rm, L4_MAP_ITEM_MAP));
#define THREAD_MAX_NUM 20
typedef struct Edf_thread { unsigned dl; // Deadline void *func; // EIP l4_cap_idx_t cap; // L4 Capability } Edf_thread;
Edf_thread thread[THREAD_MAX_NUM]; unsigned char *thread_stack[THREAD_MAX_NUM];
unsigned count = 0;
int create_l4_thread(Edf_thread *_thread) { l4_msgtag_t tag;
// Create a new task for each thread l4_cap_idx_t task_cap = l4re_util_cap_alloc(); if (l4_is_invalid_cap(task_cap)) return -1; l4_fpage_t task_fpage = l4_fpage(l4re_env()->first_free_utcb, 12, L4_CAP_FPAGE_RW); l4_factory_create_task(l4re_env()->factory, task_cap, task_fpage); //
_thread->cap = l4re_util_cap_alloc(); thread[count] = *_thread; thread_stack[count] = malloc(8 << 10);
if (l4_is_invalid_cap(_thread->cap)) return -1;
tag = l4_factory_create_thread(l4re_env()->factory, _thread->cap); if (l4_error(tag)) return -1;
l4_thread_control_start();
/*
- Of course, using the region mapper and exception handler of the current task for the newly created task fails.
- I'm getting the following kernel output:
KERNEL: Warning: CPU0: Pager of 26 is invalid (pfa=010002c0, errorcode=00000004) to 3 (pc=10002c0)- But how can I create a new region mapper?
- Or is it better to just map the old one to the new task? l4_task_map(task_cap, L4RE_THIS_TASK_CAP, ... ?)
*/ l4_thread_control_pager(l4re_env()->rm); // fails l4_thread_control_exc_handler(l4re_env()->rm); // fails
l4_thread_control_bind((l4_utcb_t *)l4re_env()->first_free_utcb, task_cap); tag = l4_thread_control_commit(_thread->cap); if (l4_error(tag)) return -2;
tag = l4_thread_ex_regs(_thread->cap, (l4_umword_t)_thread->func, (l4_umword_t)(thread_stack[count] + sizeof(thread_stack[count])), 0); if (l4_error(tag)) return -3;
// Pass the deadline of the thread to the L4 system l4_sched_param_t sp = l4_sched_param_by_type(Deadline, thread[count].dl, 0); // Let the L4 system tell the kernel to enqueue the thread in its (deadline-based) ready queue tag = l4_scheduler_run_thread(l4re_env()->scheduler, thread[count].cap, &sp); if (l4_error(tag)) return -4;
// Shift first_free_utcb for further threads l4re_env()->first_free_utcb = (l4_addr_t)l4re_env()->first_free_utcb + L4_UTCB_OFFSET;
return count++; }
Adam
Hi,
On 09/03/2014 12:32 AM, Adam Lackorzynski wrote:
And indeed, you need to map the cap to the new task.
l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_obj_fpage(l4re_env()->rm, 0, L4_FPAGE_RO), l4_map_obj_control(l4re_env()->rm, L4_MAP_ITEM_MAP));
Thanks, that works, there's no more kernel warning for an invalid pager now.
But the actual thread function is not executed any more. Instead, Fiasco calls the deblock_refill method of my ready queue implementation for that thread (respectively Sched_context) _steadily_. I've attached the output of JDB's thread list. It's interesting to see that thread0 seems to wait for the first thread of task 1a.
The function of thread0 accesses its Edf_thread object created in task 1a (named 't'), so I've tried to map that object to the new task. Additionally, I've tried to map the thread capability for thread0 ('t->cap') to the new task. But both approaches do not solve the problem.
l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_fpage((l4_umword_t)t, sizeof(t), L4_FPAGE_RW), l4_map_obj_control((l4_umword_t)&t, L4_MAP_ITEM_MAP));
l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_obj_fpage(t->cap, 0, L4_FPAGE_RW), l4_map_obj_control(t->cap, L4_MAP_ITEM_MAP));
Best regards, Valentin
On Wed Sep 03, 2014 at 15:20:31 +0200, Valentin Hauner wrote:
On 09/03/2014 12:32 AM, Adam Lackorzynski wrote:
And indeed, you need to map the cap to the new task.
l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_obj_fpage(l4re_env()->rm, 0, L4_FPAGE_RO), l4_map_obj_control(l4re_env()->rm, L4_MAP_ITEM_MAP));
Thanks, that works, there's no more kernel warning for an invalid pager now.
But the actual thread function is not executed any more. Instead, Fiasco calls the deblock_refill method of my ready queue implementation for that thread (respectively Sched_context) _steadily_. I've attached the output of JDB's thread list. It's interesting to see that thread0 seems to wait for the first thread of task 1a.
Does it work with the default scheduler?
Thread 1b is the pager and they're both seem to be in an IPC. So likely 26 cause a page-fault and the page-fault is being resolved by sending an IPC to the pager.
The function of thread0 accesses its Edf_thread object created in task 1a (named 't'), so I've tried to map that object to the new task. Additionally, I've tried to map the thread capability for thread0 ('t->cap') to the new task. But both approaches do not solve the problem.
It's likely a page-fault that happens because the address space of the new task is empty and executing the first instruction of the thread causes a page-fault on the code, that needs to be resolved by the pager.
Adam
Hi,
On 09/05/2014 12:28 AM, Adam Lackorzynski wrote:
Does it work with the default scheduler?
No, it does not work with the default Fixed_prio scheduler. Tasks are created properly and my threads are assigned to them. But after that, nothing happens. Instead, one of the created threads (thread0 - thread3) waits for the pager 1b. I've attached the code of that example for your convenience. I've removed all code that concerns the EDF scheduler, so it works with the default Fixed_prio scheduler. It's a ordinary package, so just place it under './l4/pkg' and run the binary produced by './libedft/examples/libedft-example'.
Besides, I've tried to modify your utcb-ipc example and created a new task for thread2 just as you suggested in your previous posts. It doesn't work either, thread1 outputs a 'Thread1 up' and then nothing happens (thread2 is active then). I've attached the JDB thread list output for this example.
Thanks for your effort!
Best regards, Valentin
On Fri Sep 05, 2014 at 15:05:46 +0200, Valentin Hauner wrote:
On 09/05/2014 12:28 AM, Adam Lackorzynski wrote:
Does it work with the default scheduler?
No, it does not work with the default Fixed_prio scheduler. Tasks are created properly and my threads are assigned to them. But after that, nothing happens. Instead, one of the created threads (thread0 - thread3) waits for the pager 1b. I've attached the code of that example for your convenience. I've removed all code that concerns the EDF scheduler, so it works with the default Fixed_prio scheduler. It's a ordinary package, so just place it under './l4/pkg' and run the binary produced by './libedft/examples/libedft-example'.
Your threads page-fault all around. The reason is that I was slightly wrong with my last statement on paging. The pager of the parent task resolves the page-fault however just maps the memory locally to the parent task, so the memory never appears in the child tasks. I guess you have to map the pages yourself. I guess you could just map everything from _stext & L4_PAGEMASK to _end & L4_PAGEMASk to all tasks.
Besides, I've tried to modify your utcb-ipc example and created a new task for thread2 just as you suggested in your previous posts. It doesn't work either, thread1 outputs a 'Thread1 up' and then nothing happens (thread2 is active then). I've attached the JDB thread list output for this example.
Looks like the same issue to me.
Adam
Hi,
On 09/08/2014 12:17 AM, Adam Lackorzynski wrote:
Your threads page-fault all around. The reason is that I was slightly wrong with my last statement on paging. The pager of the parent task resolves the page-fault however just maps the memory locally to the parent task, so the memory never appears in the child tasks. I guess you have to map the pages yourself. I guess you could just map everything from _stext & L4_PAGEMASK to _end & L4_PAGEMASk to all tasks.
OK, can you please give me a small example for that to get things working for my library?
The only code that I found on your website that might be relevant is: http://os.inf.tu-dresden.de/l4env/doc/html/events/demo2_2main_8c-source.html
However, there is syscalls.h included, so it seems to use an outdated version of L4Re.
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 10.09.2014 11:32, Valentin Hauner wrote:
Hi,
On 09/08/2014 12:17 AM, Adam Lackorzynski wrote:
Your threads page-fault all around. The reason is that I was slightly wrong with my last statement on paging. The pager of the parent task resolves the page-fault however just maps the memory locally to the parent task, so the memory never appears in the child tasks. I guess you have to map the pages yourself. I guess you could just map everything from _stext & L4_PAGEMASK to _end & L4_PAGEMASk to all tasks.
OK, can you please give me a small example for that to get things working for my library?
Are you looking for examples on using the l4_task_map() system call? Please consider l4/pkg/examples/sys/vmtest and l4/pkg/examples/sys/vcpu.
The only code that I found on your website that might be relevant is: http://os.inf.tu-dresden.de/l4env/doc/html/events/demo2_2main_8c-source.html
However, there is syscalls.h included, so it seems to use an outdated version of L4Re.
If it has l4env in the URL, please ignore it.
Björn
Hi,
On 09/10/2014 09:34 PM, Björn Döbel wrote:
Are you looking for examples on using the l4_task_map() system call?
No, I'm already using l4_task_map. But Adam suggested to "map everything from _stext & L4_PAGEMASK to _end & L4_PAGEMASK to all tasks", but I don't know how to realize this. What does "everything" from _stext to _end mean?
The only example that I've found looking for "_stext" and "_end" on your website was the outdated one posted yesterday.
I've tried the following:
l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_fpage(((l4_umword_t)_stext) & L4_PAGEMASK, L4_PAGESHIFT, L4_FPAGE_RW), l4_map_control((l4_umword_t)_stext, 0, L4_MAP_ITEM_MAP));
l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_fpage(((l4_umword_t)_end) & L4_PAGEMASK, L4_PAGESHIFT, L4_FPAGE_RW), l4_map_control((l4_umword_t)_end, 0, L4_MAP_ITEM_MAP));
But of course, _stext and _end are undeclared. Unfortunately, there are no further information about it on os.inf.tu-dresden.de: https://www.google.de/search?q=_stext+site%3Aos.inf.tu-dresden.de
Best regards, Valentin
Hi,
On 09/11/2014 02:13 PM, Valentin Hauner wrote:
What does "everything" from _stext to _end mean?
OK, I've found a snippet in Moe that seems to fit: It's located in ./l4/pkg/moe/server/src/main.cc lines 523 f.
I've adapted it to fit my needs, but the issue is still the same:
extern char _stext[]; extern char _end[];
for (unsigned long i = ((unsigned long)_stext & L4_PAGEMASK); i < ((unsigned long)_end & L4_PAGEMASK); i += L4_PAGESIZE) { l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_fpage(i, 0, L4_FPAGE_RO), l4_map_control(i, 0, L4_MAP_ITEM_MAP)); }
What's wrong here?
Best regards, Valentin
On Sat Sep 13, 2014 at 14:09:28 +0200, Valentin Hauner wrote:
On 09/11/2014 02:13 PM, Valentin Hauner wrote:
What does "everything" from _stext to _end mean?
OK, I've found a snippet in Moe that seems to fit: It's located in ./l4/pkg/moe/server/src/main.cc lines 523 f.
I've adapted it to fit my needs, but the issue is still the same:
extern char _stext[]; extern char _end[];
for (unsigned long i = ((unsigned long)_stext & L4_PAGEMASK); i < ((unsigned long)_end & L4_PAGEMASK); i += L4_PAGESIZE) { l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_fpage(i, 0, L4_FPAGE_RO),
l4_fpage(i, L4_LOG2_PAGESIZE, L4_FPAGE_RWX),
A size needs to be specified for the fpage. And read-only will not be enough, as for example, the stack needs to be written by the thread functions.
l4_map_control(i, 0, L4_MAP_ITEM_MAP));
}
What's wrong here?
Adam
Hi,
On 09/15/2014 12:10 AM, Adam Lackorzynski wrote:
l4_fpage(i, L4_LOG2_PAGESIZE, L4_FPAGE_RWX),
A size needs to be specified for the fpage. And read-only will not be enough, as for example, the stack needs to be written by the thread functions.
Unfortunately, the issue is still the same. I'm mapping everything from _stext & L4_PAGEMASK to _end & L4_PAGEMASK after having mapped the pager to my new task, but each time one of my created threads is still waiting for '1b'. Besides, I'm getting a huge list of kernel warnings with the new l4_fpage call that hasn't been there before. I've attached it to this mail. So basically it's still the same code that I've sent you on September 5th, but in addition, there's the following loop beginning at line 57 in lib/src/edft.c now:
extern char _stext[]; extern char _end[];
for (unsigned long i = ((unsigned long)_stext & L4_PAGEMASK); i < ((unsigned long)_end & L4_PAGEMASK); i += L4_PAGESIZE) { l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_fpage(i, L4_LOG2_PAGESIZE, L4_FPAGE_RWX), l4_map_control(i, 0, L4_MAP_ITEM_MAP)); }
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Besides, I'm getting a huge list of kernel warnings with the new l4_fpage call that hasn't been there before. I've attached it to this mail.
The kernel is complaining that you are trying to map memory from the sender that is not available in the sender's address space. As mapping basically means taking the sender's page table entries and putting them into the receiver's PT, the kernel does not know what to do.
The trick here is that your pager needs to have the binary mapped into its own address space before handing it out. This can be achieved by accessing the binary's pages once during startup. (For convenience, see the l4_touch_ro() and l4_touch_rw() functions.)
Bjoern
Hi,
thanks for your quick reply!
On 09/15/2014 09:18 AM, Björn Döbel wrote:
The trick here is that your pager needs to have the binary mapped into its own address space before handing it out. This can be achieved by accessing the binary's pages once during startup. (For convenience, see the l4_touch_ro() and l4_touch_rw() functions.)
That worked, now the warnings do not appear any more. But it does not solve the real problem either.
The code I've added:
extern char _start[], _stext[], _sdata[], _end[];
// Adapted from examples/sys/start-with-exc/main.c l4_touch_ro(_start, _sdata - _start + 1); l4_touch_rw(_sdata, _end - _sdata);
// Allocating stack and setting arguments to pass ...
l4_touch_rw(thread_stack[count], sizeof(thread_stack[count])); l4_touch_ro(t->func, 1);
// Mapping the pages with l4_task_map ...
I've tried using _stext instead of _start, but still no success.
A simple call of
l4_touch_ro(_stext, _end - _stext)
does not solve the issue either.
Best regards, Valentin
On Mon Sep 15, 2014 at 15:50:07 +0200, Valentin Hauner wrote:
On 09/15/2014 09:18 AM, Björn Döbel wrote:
The trick here is that your pager needs to have the binary mapped into its own address space before handing it out. This can be achieved by accessing the binary's pages once during startup. (For convenience, see the l4_touch_ro() and l4_touch_rw() functions.)
That worked, now the warnings do not appear any more. But it does not solve the real problem either.
The code I've added:
extern char _start[], _stext[], _sdata[], _end[];
// Adapted from examples/sys/start-with-exc/main.c l4_touch_ro(_start, _sdata - _start + 1); l4_touch_rw(_sdata, _end - _sdata);
// Allocating stack and setting arguments to pass ...
l4_touch_rw(thread_stack[count], sizeof(thread_stack[count])); l4_touch_ro(t->func, 1);
// Mapping the pages with l4_task_map ...
I've tried using _stext instead of _start, but still no success.
A simple call of
l4_touch_ro(_stext, _end - _stext)
does not solve the issue either.
I'm unsure what is the problem now. Doing the 4 l4_touch_* are the right thing to do. We should check whether there are more page faults happening. Enter jdb, then issue 'P*' (capital P) to enable page-fault logging, then 'g' for go. Let it run a second, then ESC again. Look at log with 'T' (capital T). Are there any entries? And generally, what are the threads doing?
Adam
Hi,
On 09/16/2014 12:04 AM, Adam Lackorzynski wrote:
Are there any entries?
Yes, there are produced more than thousand identical entries in less than a second:
pf: 0026 pfa=00004f3c ip=01000200 (w-) spc=0xfcffae94 err=6
'26' is the id of the thread that is waiting for '1b'.
On 09/16/2014 12:04 AM, Adam Lackorzynski wrote:
And generally, what are the threads doing?
They are doing a colored Hello World output. It's still the same code that I've sent you on September 5th in the zip file. You can find the thread function(s) in examples/libedft-example/main.c.
Today, I've tested a very minimal example reducing the thread functions to nothing else but a simple 'printf("Hello World!");', but it's still the same issue.
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 16.09.2014 13:15, Valentin Hauner wrote:
Hi,
On 09/16/2014 12:04 AM, Adam Lackorzynski wrote:
Are there any entries?
Yes, there are produced more than thousand identical entries in less than a second:
pf: 0026 pfa=00004f3c ip=01000200 (w-) spc=0xfcffae94 err=6
So you are triggering a write page fault at address 0x4f3c. The faulting instruction is at 0x1000200.
* What is this instruction? * What address is this? It does not seem to be part of the binary as it is far off the instruction address. * Does this page fault appear in your pager? (It should?) * What are you sending as a reply to this page fault?
Bjoern
Hi,
thanks again for your quick reply!
On 09/16/2014 01:21 PM, Björn Döbel wrote:
- What is this instruction?
- What address is this? It does not seem to be part of the binary as it is far off the instruction address.
- Does this page fault appear in your pager? (It should?)
- What are you sending as a reply to this page fault?
I'm not sure how to get any further information of this instruction. The JDB manual did not provide any help for that.
Moreover, I guess it's not possible to deduce the line of code in my C files from that instruction pointer, is it? Special pre-compiler debugging features would be necessary for that.
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 16.09.2014 13:40, Valentin Hauner wrote:
Hi,
thanks again for your quick reply!
On 09/16/2014 01:21 PM, Björn Döbel wrote:
- What is this instruction? * What address is this? It does not
seem to be part of the binary as it is far off the instruction address. * Does this page fault appear in your pager? (It should?) * What are you sending as a reply to this page fault?
I'm not sure how to get any further information of this instruction. The JDB manual did not provide any help for that.
Moreover, I guess it's not possible to deduce the line of code in my C files from that instruction pointer, is it? Special pre-compiler debugging features would be necessary for that.
Know your tools!
man objdump man addr2line man nm man gcc / man clang man gdb
Bjoern
- -- Dipl.-Inf. Bjoern Doebel Mail: doebel@tudos.org TU Dresden, OS Chair Phone: +49 351 463 38 799 Noethnitzer Str. 46 Fax: +49 351 463 38 284 01187 Dresden, Germany WWW: http://www.tudos.org/~doebel - -- "When the seagulls follow the trawler, it's because they think sardines will be thrown into the sea." (Eric Cantona)
Hi,
thanks, I've used addr2line and found out that it was the head of thread_func (l. 27 in examples/libedft-example/main.c). So it seems that the stack I'm using for passing arguments to the thread function is the problem. As I am creating a dynamic number of threads, it does not make sense for me to create the stack object(s) statically as you guys do it in examples/sys/utcb-ipc/main.c. So until now, I've allocated memory on the _heap_ with malloc for each thread stack (l. 61 in lib/src/edft.c). But after creating 4 stacks for 4 example threads statically similiar to the utcb-ipc example, the page fault at 0x1000200 is gone.
However, for each of the 4 threads, I'm getting a new page fault at 0:
L4Re[rm]: unhandled read page fault @0 pc=0 L4Re: unhandled exception: pc=0x0
L4Re[rm]: unhandled read page fault @0 pc=0 L4Re: unhandled exception: pc=0x0
L4Re[rm]: unhandled read page fault @0 pc=0 L4Re: unhandled exception: pc=0x0
L4Re[rm]: unhandled read page fault @0 pc=0 L4Re: unhandled exception: pc=0x0
Why is this?
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 16.09.2014 15:26, Valentin Hauner wrote:
Hi,
thanks, I've used addr2line and found out that it was the head of thread_func (l. 27 in examples/libedft-example/main.c). So it seems that the stack I'm using for passing arguments to the thread function is the problem. As I am creating a dynamic number of threads, it does not make sense for me to create the stack object(s) statically as you guys do it in examples/sys/utcb-ipc/main.c. So until now, I've allocated memory on the _heap_ with malloc for each thread stack (l. 61 in lib/src/edft.c).
Just to be sure: How large is this per-thread stack? Are you properly aligning it to page boundaries? Otherwise you might miss mapping some parts of the stack. (Mappings always base on hardware memory pages, that's why your stack should be a multiple of a page size large and start at an address that is the start of a page.)
But after creating 4 stacks for 4 example threads statically similiar to the utcb-ipc example, the page fault at 0x1000200 is gone.
It's a bad idea to figure this out before you fix the previous problem. Let's keep complexity low.
Bjoern - -- Dipl.-Inf. Bjoern Doebel Mail: doebel@tudos.org TU Dresden, OS Chair Phone: +49 351 463 38 799 Noethnitzer Str. 46 Fax: +49 351 463 38 284 01187 Dresden, Germany WWW: http://www.tudos.org/~doebel - -- "When the seagulls follow the trawler, it's because they think sardines will be thrown into the sea." (Eric Cantona)
Hi,
On 09/16/2014 03:54 PM, Björn Döbel wrote:
Just to be sure: How large is this per-thread stack? Are you properly aligning it to page boundaries?
Adam suggested to give it a size of 2000 * l4_umword_t (THREAD_STACK_SIZE is set to 2000) in his mail from September 3th, so I'm using the following code:
thread_stack[count] = malloc(THREAD_STACK_SIZE * sizeof(l4_umword_t)); // For x86-32, the arguments of functions are passed via the stack thread_stack[count][THREAD_STACK_SIZE - 1] = (l4_umword_t)t->arg; thread_stack[count][THREAD_STACK_SIZE - 2] = 0; // ... l4_touch_rw(thread_stack[count], sizeof(thread_stack[count])); // ... l4_thread_ex_regs(t->cap, (l4_umword_t)t->func,
(l4_umword_t)&thread_stack[count][THREAD_STACK_SIZE - 2], 0);
Header of the thread function:
void thread_func(l4_umword_t data) { /* ... */ }
That's the whole stack-relevant code in my library. With one task for all threads only, everything works.
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 16.09.2014 16:22, Valentin Hauner wrote:
Hi,
On 09/16/2014 03:54 PM, Björn Döbel wrote:
Just to be sure: How large is this per-thread stack? Are you properly aligning it to page boundaries?
Adam suggested to give it a size of 2000 * l4_umword_t (THREAD_STACK_SIZE is set to 2000) in his mail from September 3th, so I'm using the following code:
thread_stack[count] = malloc(THREAD_STACK_SIZE * sizeof(l4_umword_t)); // For x86-32, the arguments of functions are passed via the stack thread_stack[count][THREAD_STACK_SIZE - 1] = (l4_umword_t)t->arg; thread_stack[count][THREAD_STACK_SIZE - 2] = 0; // ... l4_touch_rw(thread_stack[count], sizeof(thread_stack[count])); // ... l4_thread_ex_regs(t->cap, (l4_umword_t)t->func,
(l4_umword_t)&thread_stack[count][THREAD_STACK_SIZE - 2], 0);
How is thread_stack declared?
What call are you using to map the actual stack to the task?
Header of the thread function:
void thread_func(l4_umword_t data) { /* ... */ }
That's the whole stack-relevant code in my library. With one task for all threads only, everything works.
Can you please clarify what you mean with the last sentence?
Bjoern - -- Dipl.-Inf. Bjoern Doebel Mail: doebel@tudos.org TU Dresden, OS Chair Phone: +49 351 463 38 799 Noethnitzer Str. 46 Fax: +49 351 463 38 284 01187 Dresden, Germany WWW: http://www.tudos.org/~doebel - -- "When the seagulls follow the trawler, it's because they think sardines will be thrown into the sea." (Eric Cantona)
Hi,
On 09/17/2014 08:02 AM, Björn Döbel wrote:
How is thread_stack declared?
It's declared on line 21 in lib/src/edft.c:
l4_umword_t *thread_stack[THREAD_MAX_NUM];
Currently, THREAD_MAX_NUM is set to 20.
What call are you using to map the actual stack to the task?
I thought that the mapping of the stack happens when iterating from _start & L4_PAGEMASK to _end & L4_PAGEMASK and mapping the single pages. Before that loop, I do a read-write touch on the stack:
l4_touch_rw(thread_stack[count], sizeof(thread_stack[count]));
I tried to map the stack array separately, but I failed because l4_task_map wants a l4_fpage_t object that does not fit to the type of the stack array.
Can you please clarify what you mean with the last sentence?
The execution of all threads including the access on the function parameters on the stack works if I assign all threads to L4RE_THIS_TASK_CAP and do not create new tasks.
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 17.09.2014 09:26, Valentin Hauner wrote:
Hi,
On 09/17/2014 08:02 AM, Björn Döbel wrote:
How is thread_stack declared?
It's declared on line 21 in lib/src/edft.c:
l4_umword_t *thread_stack[THREAD_MAX_NUM];
Currently, THREAD_MAX_NUM is set to 20.
What call are you using to map the actual stack to the task?
I thought that the mapping of the stack happens when iterating from _start & L4_PAGEMASK to _end & L4_PAGEMASK and mapping the single pages.
That is unlikely. The range [_start, _end] only contains static memory that comes from your binary (i.e., the code and data sections). Your thread stacks are allocated dynamically from the parent's heap and therefore lie outside this range. You will have to map those pages manually.
Before that loop, I do a read-write touch on the stack:
l4_touch_rw(thread_stack[count], sizeof(thread_stack[count]));
I tried to map the stack array separately, but I failed because l4_task_map wants a l4_fpage_t object that does not fit to the type of the stack array.
An fpage() wants an address and a size. Your malloc() call yields an address (note: this is probably unaligned, maybe prefer to use posix_memalign()), the size is what you pass to malloc(). What would be the problem?
Can you please clarify what you mean with the last sentence?
The execution of all threads including the access on the function parameters on the stack works if I assign all threads to L4RE_THIS_TASK_CAP and do not create new tasks.
That is, if you execute the thread code within the parent?
Bjoern
Hi,
On 09/17/2014 10:23 AM, Björn Döbel wrote:
An fpage() wants an address and a size. Your malloc() call yields an address (note: this is probably unaligned, maybe prefer to use posix_memalign()), the size is what you pass to malloc(). What would be the problem?
Still the same problem, I'm getting page faults at the head of the thread function with the following new code:
// Out of function l4_umword_t *thread_stacks[THREAD_MAX_NUM]; // ... void foo() { // ... unsigned stack_size = THREAD_STACK_SIZE * sizeof(l4_umword_t); if (posix_memalign((void**)&thread_stacks[count], (size_t)L4_LOG2_PAGESIZE, (size_t)stack_size) != 0) return -1; // ... l4_touch_rw(thread_stacks[count], stack_size); l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_fpage((unsigned long)thread_stacks[count],
stack_size, L4_FPAGE_RWX),
l4_map_control((l4_umword_t)thread_stacks[count], 0, L4_MAP_ITEM_MAP));
// ... }
That is, if you execute the thread code within the parent?
Yes, I simply bind the new threads to the current task (L4RE_THIS_TASK_CAP) in this case.
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 17.09.2014 14:30, Valentin Hauner wrote:
Hi,
On 09/17/2014 10:23 AM, Björn Döbel wrote:
An fpage() wants an address and a size. Your malloc() call yields an address (note: this is probably unaligned, maybe prefer to use posix_memalign()), the size is what you pass to malloc(). What would be the problem?
Still the same problem, I'm getting page faults at the head of the thread function with the following new code:
// Out of function l4_umword_t *thread_stacks[THREAD_MAX_NUM]; // ... void foo() { // ... unsigned stack_size = THREAD_STACK_SIZE * sizeof(l4_umword_t); if (posix_memalign((void**)&thread_stacks[count], (size_t)L4_LOG2_PAGESIZE, (size_t)stack_size) != 0) return -1; // ... l4_touch_rw(thread_stacks[count], stack_size); l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_fpage((unsigned long)thread_stacks[count],
stack_size, L4_FPAGE_RWX),
l4_map_control((l4_umword_t)thread_stacks[count], 0, L4_MAP_ITEM_MAP));
// ... }
For starting a single thread:
* What is thread_stacks[thread.id]? * What is the stack pointer you are setting at thread startup? * Is any of these addresses related to the page fault address you are seeing?
That is, if you execute the thread code within the parent?
Yes, I simply bind the new threads to the current task (L4RE_THIS_TASK_CAP) in this case.
Sure, because then memory is managed by L4Re instead of your own pager and the thread is running in the same address space as its creator.
You probably already mentioned it, but this thread has grown quite long: Why do you actually have to launch threads in a different AS and implement your own pager?
Bjoern
Hi,
was the alignment correct?
On 09/17/2014 02:53 PM, Björn Döbel wrote:
- What is thread_stacks[thread.id]?
It's the stack of that thread organized in an array, as suggested by Adam. The stack is prefilled with data:
thread_stacks[count][THREAD_STACK_SIZE - 1] = (l4_umword_t)thread->arg; thread_stacks[count][THREAD_STACK_SIZE - 2] = 0;
where 'thread->arg' is some argument to pass to the thread.
- What is the stack pointer you are setting at thread startup?
Again suggested by Adam, I'm setting thread_stacks[count][1998] as SP:
l4_thread_ex_regs(thread->cap, (l4_umword_t)thread->func,
(l4_umword_t)&thread_stacks[count][THREAD_STACK_SIZE - 2], 0);
- Is any of these addresses related to the page fault address you are seeing?
OK, I've found out something new. In the trace buffer, I'm getting the following entry:
pf: 0026 pfa=0000b014 ip=01000200 (w-) spc=0xfcffae94 err=6
The IP points to the head of the thread function, the pfa is &thread_stacks[count][THREAD_STACK_SIZE - 3]. But why?
You probably already mentioned it, but this thread has grown quite long: Why do you actually have to launch threads in a different AS and implement your own pager?
Yeah, I hope to fix this problem soon, because the EDF scheduler is part of my Bachelor's thesis. The concept requires the possibility to run the threads in different spaces due to security reasons.
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 17.09.2014 15:29, Valentin Hauner wrote:
Hi,
was the alignment correct?
I don't know as you didn't tell us about the return value you got from malloc/memalign.
On 09/17/2014 02:53 PM, Björn Döbel wrote:
- What is thread_stacks[thread.id]?
It's the stack of that thread organized in an array, as suggested by Adam. The stack is prefilled with data:
thread_stacks[count][THREAD_STACK_SIZE - 1] = (l4_umword_t)thread->arg; thread_stacks[count][THREAD_STACK_SIZE
- 2] = 0;
where 'thread->arg' is some argument to pass to the thread.
I was enquiring about the actual value. :)
- What is the stack pointer you are setting at thread startup?
Again suggested by Adam, I'm setting thread_stacks[count][1998] as SP:
l4_thread_ex_regs(thread->cap, (l4_umword_t)thread->func,
(l4_umword_t)&thread_stacks[count][THREAD_STACK_SIZE - 2], 0);
Yes, but what IS this value, numerically?
- Is any of these addresses related to the page fault address you
are seeing?
OK, I've found out something new. In the trace buffer, I'm getting the following entry:
pf: 0026 pfa=0000b014 ip=01000200 (w-) spc=0xfcffae94 err=6
The IP points to the head of the thread function, the pfa is &thread_stacks[count][THREAD_STACK_SIZE - 3]. But why?
Maybe because your program is trying to push data onto the stack? I have no idea because you did not tell us about the actual instruction at address 0x1000200.
Bjoern
Hi,
thanks again for your reply!
On 09/17/2014 03:47 PM, Björn Döbel wrote:
I don't know as you didn't tell us about the return value you got from malloc/memalign.
It was 0, so no error.
I was enquiring about the actual value. Yes, but what IS this value, numerically?
Values in decimal notation:
thread_stacks[count]: 12320 thread_stacks[count][0]: 0 thread_stacks[count][THREAD_STACK_SIZE - 1]: 0 (for thread with no. 0) thread_stacks[count][THREAD_STACK_SIZE - 2]: 0
Maybe because your program is trying to push data onto the stack? I have no idea because you did not tell us about the actual instruction at address 0x1000200.
It's simply the head of the function. addr2line gives me line 27 of examples/libedft-example/main.c, so it's the opening bracket of the thread function:
void thread_func(l4_umword_t no) { /* line 27 */ printf("Hello World!\n"); edft_release_cap(no); }
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Values in decimal notation:
thread_stacks[count]: 12320
In hex that is 0x3020 -> This address is certainly not aligned to a page boundary. That would be something like 0x3000 or 0x4000.
I just saw in your previous email that you are calling memalign like this:
posix_memalign((void**)&thread_stacks[count], (size_t)L4_LOG2_PAGESIZE, (size_t)stack_size)
The second argument to this function is the alignment. Let's have a look at the man page:
"The address of the allocated memory will be a multiple of alignment, which must be a power of two and a multiple of sizeof(void *)."
You are passing L4_LOG2_PAGESIZE, which is defined as an alias to L4_PAGESHIFT and hence equals 12 (note: not a power of 2). You want to pass L4_PAGESIZE here, which is 4096 and fulfills the constraints mentioned in the manpage.
thread_stacks[count][0]: 0 thread_stacks[count][THREAD_STACK_SIZE - 1]: 0 (for thread with no. 0) thread_stacks[count][THREAD_STACK_SIZE - 2]: 0
Maybe because your program is trying to push data onto the stack? I have no idea because you did not tell us about the actual instruction at address 0x1000200.
It's simply the head of the function. addr2line gives me line 27 of examples/libedft-example/main.c, so it's the opening bracket of the thread function:
void thread_func(l4_umword_t no) { /* line 27 */ printf("Hello World!\n"); edft_release_cap(no); }
Usually, your compiler generates a certain number of prefix instructions for every function. The prefix for GCC is something like
PUSH EBP MOV EBP, ESP
(to validate this: use objdump to disassemble your binary and check what is there at address 0x1000200.).
So, this instruction is likely to be a PUSH. Hence your program will try to write to the next machine word BELOW your intially set stack pointer. (Again, check with objdump if in doubt.)
In the end means, that your stack mapping did not succeed as intended. Your reported PF address was also 0xb014, therefore I would suggest checking
* Are you really mapping to the proper stack address? -> printf() the values that you put into the task_map() call. * Does the mapping work? -> you can put an enter_kdebug("") after the task_map call. At this point the target address space will not have the memory actually mapped, hence dumping the address will show you empty memory. However, you could check the target's page table (JDB command 'p<taskno>') for the respective entry.
Bjoern - -- Dipl.-Inf. Bjoern Doebel Mail: doebel@tudos.org TU Dresden, OS Chair Phone: +49 351 463 38 799 Noethnitzer Str. 46 Fax: +49 351 463 38 284 01187 Dresden, Germany WWW: http://www.tudos.org/~doebel - -- "When the seagulls follow the trawler, it's because they think sardines will be thrown into the sea." (Eric Cantona)
Hi,
On 09/17/2014 04:31 PM, Björn Döbel wrote:
In the end means, that your stack mapping did not succeed as intended.
OK, that helped. Indeed, some of the arguments concerning the size of the area to map were wrong. Now, there is no page fault on the stack any more.
Then, I got the following pf:
pf: 0026 pfa=affff800 ip=affff800 (r-) spc=0xfcffae94 err=4
Using objdump on my binary, I've found out that it has something to do with 'l4sys_invoke_direct'. In the end, I've mapped this address to the new task, and the page fault is gone. Is there any more elegant way to do this?
The next page fault I'm getting is this: pf: 0026 pfa=b1007f1c ip=01009980 (r-) spc=0xfcffae94 err=4 A call of addr2line on 0x01009980 gives me:
l4/pkg/uclibc/lib/uclibc/_exit.cc:14
I guess it's related with the call of exit at the end of my thread function.
void thread_func(l4_umword_t cap) { printf("Hello World!\n"); exit(0); }
If I remove that exit call, I will get a read page fault on pc=0 since the function tries to jump back to its caller, but there is no caller, so the address lying on the stack is 0.
How can I map all those library functions to my new task?
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 18.09.2014 09:19, Valentin Hauner wrote:
Hi,
On 09/17/2014 04:31 PM, Björn Döbel wrote:
In the end means, that your stack mapping did not succeed as intended.
OK, that helped. Indeed, some of the arguments concerning the size of the area to map were wrong. Now, there is no page fault on the stack any more.
Yay!
Then, I got the following pf:
pf: 0026 pfa=affff800 ip=affff800 (r-) spc=0xfcffae94 err=4
Using objdump on my binary, I've found out that it has something to do with 'l4sys_invoke_direct'. In the end, I've mapped this address to the new task, and the page fault is gone. Is there any more elegant way to do this?
At this address L4Re applications by default have the "Kerne Info Page" mapped. The KIP contains information about the underlying kernel, a field for reading the current time (similar to Linux' vDSO) and the entry code for system calls. The page fault you are getting is because your program is executing its first system call and needs to read this code.
Simply mapping the creator's KIP to the same address in the new task will do the trick as you found out.
The next page fault I'm getting is this: pf: 0026 pfa=b1007f1c ip=01009980 (r-) spc=0xfcffae94 err=4 A call of addr2line on 0x01009980 gives me:
l4/pkg/uclibc/lib/uclibc/_exit.cc:14
I guess it's related with the call of exit at the end of my thread function.
void thread_func(l4_umword_t cap) { printf("Hello World!\n"); exit(0); }
Did you see the printf() output before?
If I remove that exit call, I will get a read page fault on pc=0 since the function tries to jump back to its caller, but there is no caller, so the address lying on the stack is 0.
How can I map all those library functions to my new task?
These functions are already there - you see this because your code actually reaches and executes the instruction at 0x1009980.
The problem you have is that you are starting an application on Fiasco.OC without the L4Re binary attached to your program. (Again, I'm still not getting, why you want to do this, but nevermind.)
When I have a look at the _exit() function you found, then what this function does is to send an exit signal to its L4Re parent. This concept does not exist in your setup and the access to the L4Re::global_env->parent member is probably what is causing your thread to raise a page fault.
Couple of solutions:
1) Use L4Re instead of rolling your own environment. 2) Do not call exit(), but have your threads simply do an infinite sleep(). You will see how this works in the implementation of _exit(), because this is what this function does as well. 3) Implement your own version of exit that notifies the creator so that the creator can perform the necessary cleanup work.
L4Re actually implements a combination of variants 2 + 3.
- From a semantic perspective: calling exit() in multithreaded programs is likely to not do what you intend. exit() terminates the running program regardless of what progress the other threads are making, it does NOT simply terminate a thread. (This is not L4-specific, this is what the POSIX standard says.)
Bjoern
- -- Dipl.-Inf. Bjoern Doebel Mail: doebel@tudos.org TU Dresden, OS Chair Phone: +49 351 463 38 799 Noethnitzer Str. 46 Fax: +49 351 463 38 284 01187 Dresden, Germany WWW: http://www.tudos.org/~doebel - -- "When the seagulls follow the trawler, it's because they think sardines will be thrown into the sea." (Eric Cantona)
Hi,
the infinite sleep did it, no page faults any more. Thanks! :)
On 09/18/2014 09:29 AM, Björn Döbel wrote:
Did you see the printf() output before?
No, that's the only problem I'm struggling with at the moment. There's no error message or the like, but the output does simply not appear. What might be the reason for that? A call of 'fflush(stdout);' does not do the trick either.
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 09/18/2014 09:29 AM, Björn Döbel wrote:
Did you see the printf() output before?
No, that's the only problem I'm struggling with at the moment. There's no error message or the like, but the output does simply not appear. What might be the reason for that? A call of 'fflush(stdout);' does not do the trick either.
L4Re's printf() (which you are using) sends the printed message to the application's LOG capability. As you are setting up a new task, I am guessing that you do not pass any initial set of capabilities with it (another advantage you'd get by using L4Re's default application loader btw).
So what I guess happens is that printf() tries to send a message to LOG. LOG is undefined, hence an invalid cap. The kernel will return an error instead of sending the message, but you don't see this error as you are not checking printf()'s return value.
To confirm this, you could try using IPC logging in JDB (I*, IR+, run for some time, then T for the trace buffer.)
Bjoern
Hi,
On 09/18/2014 04:51 PM, Björn Döbel wrote:
(another advantage you'd get by using L4Re's default application loader btw).
OK, I'm aware of the fact that all the things I'm implementing manually here have already been implemented by you in the default loader. The reason I want to use the C (or C++) interface for communicating with L4Re and Fiasco.OC is its flexibility. The Lua scripts do not provide this flexibility that C or any other programming language can offer.
So what I guess happens is that printf() tries to send a message to LOG. LOG is undefined, hence an invalid cap.
Yes, the trace buffer contains an corresponding entry with errno=4 ('not existent').
Is there any simple possibility to do some output in my case? Can I assign LOG to the new task?
Best regards, Valentin
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 18.09.2014 17:12, Valentin Hauner wrote:
Hi,
On 09/18/2014 04:51 PM, Björn Döbel wrote:
(another advantage you'd get by using L4Re's default application loader btw).
OK, I'm aware of the fact that all the things I'm implementing manually here have already been implemented by you in the default loader. The reason I want to use the C (or C++) interface for communicating with L4Re and Fiasco.OC is its flexibility. The Lua scripts do not provide this flexibility that C or any other programming language can offer.
I'm not buying this argument. But that might be my lack of understanding for your situation.
So what I guess happens is that printf() tries to send a message to LOG. LOG is undefined, hence an invalid cap.
Yes, the trace buffer contains an corresponding entry with errno=4 ('not existent').
Is there any simple possibility to do some output in my case? Can I assign LOG to the new task?
Well, you need to make sure that your new task gets those initial caps. You can map capabilities similar to memory fpages. The default setup of initial remote caps happens in l4re/pkg/libloader/include/remote_app_model. For logging you might just map your creator's LOG cap to the same cap index in the new task.
Bjoern
Hi,
On 09/18/2014 05:11 PM, Björn Döbel wrote:
For logging you might just map your creator's LOG cap to the same cap index in the new task.
That worked, the following mapping did it:
l4_task_map(task_cap, L4RE_THIS_TASK_CAP, l4_obj_fpage(l4re_env()->log, 0, L4_FPAGE_RO), l4_map_obj_control(l4re_env()->log,
L4_MAP_ITEM_MAP));
Thanks again for the effortful support you both provided!
Best regards, Valentin
l4-hackers@os.inf.tu-dresden.de