Motherboard Forums


Reply
Thread Tools Display Modes

Re: Delta Queue Help - Paging Mr. Kirwan

 
 
Jon Kirwan
Guest
Posts: n/a
 
      09-25-2011, 02:59 PM
On Sun, 25 Sep 2011 15:18:14 +0200, Arlet Ottens
<(E-Mail Removed)> wrote:

>On 09/25/2011 02:56 PM, eeboy wrote:
>
><snip>
>
>> This does bring up a question though. If I am making a stack for some
>> function. It seams it would be easy to allocate space for it as it would be
>> some base value plus whatever space for autos... but if that function calls
>> another sub which might call another sub which might... see where I am
>> going with that question? How do I allocate? I know that I use some large
>> char arrays (~128b) for sprintf. I guess those should be static huh?

>
>If you make those arrays static, you have to keep in mind that printf()
>will no longer be reentrant. This could be a problem if you call that
>printf() function in a task, do a context switch in the middle of it,
>and have the other task use the same static buffer. An auto variable
>doesn't have that problem, but will require a suitably large stack to
>accommodate it. A static buffer protected by a semaphore would also be
>an option.


It's probably starting to get confusing. I'm not sure, even,
what is being asked by eeboy. But your response, Arlet,
needs some clarification I think. I'll use your comments as
a foil, but I'm really responding to eeboy and not you.

....

Often, what I may do is set up each thread in a separate c
file. And I then don't publish (make 'extern') any static
data I define that I don't want other threads using or
messing with.

This works just fine. It's just fine to use static arrays in
each thread and it's not even risky, so long as you make sure
that other threads don't use the same static regions.

You mentioned sprintf(). Let's say you don't have enough
sram laying about on your micro. So you simply *must* use
the same buffer for sprintf(), in all threads, because you
have no other choice in the matter. Do you have a problem?
Maybe. Not necessarily.

We've been discussing a non-preemptive design all along. Keep
that in mind. Yes, if the system were preemptive and could
literally _tear_ control away from you, it would be a problem
and _then_ you probably would need a semaphore to help
arbitrate access to the buffer for sprintf(). But let's say
this is NOT preemptive. In that case, there is no problem.
When you call sprintf(), unless you re-write it, it will do
the work you asked and then return. But since this is a
cooperative system and changes to other threads can only
occur when you call the thread switch code, there is no way
for interference from other threads. You have control over
the cpu, so there is no problem. So long as you get a chance
to _use_ the buffer before you switch threads, or copy the
part of it you need somewhere else, first.

It's not nearly as scary as some are making this sound.
Especially not if you are staying cooperative.

Now, if you go preemptive, then yes. All hell breaks loose.
It's possible that there is static memory being used in some
floating point code you don't even know you are using. So
you have thread T1 in the middle of some expression calc and
then the operating system 'preempts' you and forces control
over to thread T2. But the floating point code was not
written for a preemptive operating system and the author,
stilly idiot as he or she may be, used some static memory
that is entirely internal to their code for temporary storage
during computation. But T2 now starts up a calculation, or
perhaps comes back to one it thinks is in progress, and it's
just BAD. Nothing works and you've no idea why your numbers
aren't right. The only fix is to make the context switch
code aware of all these library static areas and save them
away. Or else block switching when a library routine is
running. Stuff like that. It gets really bad, fast.

Which is why I don't recommend pre-emption as your first
attempt.

Anyway, I'll answer other stuff elsewhere, shortly.

Jon
 
Reply With Quote
 
 
 
 
Arlet Ottens
Guest
Posts: n/a
 
      09-25-2011, 03:22 PM
On 09/25/2011 04:59 PM, Jon Kirwan wrote:
> On Sun, 25 Sep 2011 15:18:14 +0200, Arlet Ottens
> <(E-Mail Removed)> wrote:
>
>> On 09/25/2011 02:56 PM, eeboy wrote:
>>
>> <snip>
>>
>>> This does bring up a question though. If I am making a stack for some
>>> function. It seams it would be easy to allocate space for it as it would be
>>> some base value plus whatever space for autos... but if that function calls
>>> another sub which might call another sub which might... see where I am
>>> going with that question? How do I allocate? I know that I use some large
>>> char arrays (~128b) for sprintf. I guess those should be static huh?

>>
>> If you make those arrays static, you have to keep in mind that printf()
>> will no longer be reentrant. This could be a problem if you call that
>> printf() function in a task, do a context switch in the middle of it,
>> and have the other task use the same static buffer. An auto variable
>> doesn't have that problem, but will require a suitably large stack to
>> accommodate it. A static buffer protected by a semaphore would also be
>> an option.

>
> It's probably starting to get confusing. I'm not sure, even,
> what is being asked by eeboy. But your response, Arlet,
> needs some clarification I think. I'll use your comments as
> a foil, but I'm really responding to eeboy and not you.
>
> ....
>
> Often, what I may do is set up each thread in a separate c
> file. And I then don't publish (make 'extern') any static
> data I define that I don't want other threads using or
> messing with.
>
> This works just fine. It's just fine to use static arrays in
> each thread and it's not even risky, so long as you make sure
> that other threads don't use the same static regions.
>
> You mentioned sprintf(). Let's say you don't have enough
> sram laying about on your micro. So you simply *must* use
> the same buffer for sprintf(), in all threads, because you
> have no other choice in the matter. Do you have a problem?
> Maybe. Not necessarily.
>
> We've been discussing a non-preemptive design all along. Keep
> that in mind. Yes, if the system were preemptive and could
> literally _tear_ control away from you, it would be a problem
> and _then_ you probably would need a semaphore to help
> arbitrate access to the buffer for sprintf(). But let's say
> this is NOT preemptive. In that case, there is no problem.
> When you call sprintf(), unless you re-write it, it will do
> the work you asked and then return. But since this is a
> cooperative system and changes to other threads can only
> occur when you call the thread switch code, there is no way
> for interference from other threads. You have control over
> the cpu, so there is no problem. So long as you get a chance
> to _use_ the buffer before you switch threads, or copy the
> part of it you need somewhere else, first.


A common scenenario is the following:

sprintf( buffer, "hello world\n" );
uart_sendstring( buffer );

Now, if your uart_sendstring() puts stuff on an transmit FIFO for the
UART, and the FIFO happens to be full, you'd usually want the task to
sleep until there's some room in the FIFO.

While the task is sleeping, another task is scheduled, that also
performs a sprintf() overwriting the buffer that was still used.
 
Reply With Quote
 
 
 
 
Jon Kirwan
Guest
Posts: n/a
 
      09-25-2011, 04:24 PM
On Sun, 25 Sep 2011 17:22:17 +0200, Arlet Ottens
<(E-Mail Removed)> wrote:

>On 09/25/2011 04:59 PM, Jon Kirwan wrote:
>> On Sun, 25 Sep 2011 15:18:14 +0200, Arlet Ottens
>> <(E-Mail Removed)> wrote:
>>
>>> On 09/25/2011 02:56 PM, eeboy wrote:
>>>
>>> <snip>
>>>
>>>> This does bring up a question though. If I am making a stack for some
>>>> function. It seams it would be easy to allocate space for it as it would be
>>>> some base value plus whatever space for autos... but if that function calls
>>>> another sub which might call another sub which might... see where I am
>>>> going with that question? How do I allocate? I know that I use some large
>>>> char arrays (~128b) for sprintf. I guess those should be static huh?
>>>
>>> If you make those arrays static, you have to keep in mind that printf()
>>> will no longer be reentrant. This could be a problem if you call that
>>> printf() function in a task, do a context switch in the middle of it,
>>> and have the other task use the same static buffer. An auto variable
>>> doesn't have that problem, but will require a suitably large stack to
>>> accommodate it. A static buffer protected by a semaphore would also be
>>> an option.

>>
>> It's probably starting to get confusing. I'm not sure, even,
>> what is being asked by eeboy. But your response, Arlet,
>> needs some clarification I think. I'll use your comments as
>> a foil, but I'm really responding to eeboy and not you.
>>
>> ....
>>
>> Often, what I may do is set up each thread in a separate c
>> file. And I then don't publish (make 'extern') any static
>> data I define that I don't want other threads using or
>> messing with.
>>
>> This works just fine. It's just fine to use static arrays in
>> each thread and it's not even risky, so long as you make sure
>> that other threads don't use the same static regions.
>>
>> You mentioned sprintf(). Let's say you don't have enough
>> sram laying about on your micro. So you simply *must* use
>> the same buffer for sprintf(), in all threads, because you
>> have no other choice in the matter. Do you have a problem?
>> Maybe. Not necessarily.
>>
>> We've been discussing a non-preemptive design all along. Keep
>> that in mind. Yes, if the system were preemptive and could
>> literally _tear_ control away from you, it would be a problem
>> and _then_ you probably would need a semaphore to help
>> arbitrate access to the buffer for sprintf(). But let's say
>> this is NOT preemptive. In that case, there is no problem.
>> When you call sprintf(), unless you re-write it, it will do
>> the work you asked and then return. But since this is a
>> cooperative system and changes to other threads can only
>> occur when you call the thread switch code, there is no way
>> for interference from other threads. You have control over
>> the cpu, so there is no problem. So long as you get a chance
>> to _use_ the buffer before you switch threads, or copy the
>> part of it you need somewhere else, first.

>
>A common scenenario is the following:
>
>sprintf( buffer, "hello world\n" );
>uart_sendstring( buffer );
>
>Now, if your uart_sendstring() puts stuff on an transmit FIFO for the
>UART, and the FIFO happens to be full, you'd usually want the task to
>sleep until there's some room in the FIFO.
>
>While the task is sleeping, another task is scheduled, that also
>performs a sprintf() overwriting the buffer that was still used.


Oh, yes!!

As I said, so long as you do what needs to be done _before_
allowing a context switch, it is fine. Your case is common
and would violate my cautionary point. So good to bring it
up.

Jon
 
Reply With Quote
 
 
 
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Delta Queue Help - Paging Mr. Kirwan Jon Kirwan Embedded 0 09-25-2011 04:46 PM
Re: Delta Queue Help - Paging Mr. Kirwan Jon Kirwan Embedded 0 09-25-2011 04:19 PM
Re: Delta Queue Help - Paging Mr. Kirwan Jon Kirwan Embedded 1 09-21-2011 02:20 PM
Re: Delta Queue Help - Paging Mr. Kirwan Jon Kirwan Embedded 12 09-21-2011 11:21 AM
Delta Queue Help - Paging Mr. Kirwan eeboy Embedded 13 09-17-2011 11:43 AM


All times are GMT. The time now is 07:07 AM.


Welcome!
Welcome to Motherboard Point
 

Advertisment