On 15 Oct 2010, at 16:31, Andrew Brunner wrote:

On Fri, Oct 15, 2010 at 9:24 AM, Jonas Maebe <jonas.ma...@elis.ugent.be > wrote:
You replaced a bunch of semaphore create/lock/unlock/destroy operations with
calls to a function that does not do anything.

I did not.  I REMOVED create/destroy/lock/unlock.  I ADDED calls to
the ThreadManager's own functions for thread Resume and Suspend.

Yes, that's what I meant, because the ThreadManeger's SuspendThread function does not do anything under Unix.

Did
you try executing the suspend command?  What happened?

First of all, if you use tthread.create(true) (i.e., create a suspended thread), then the "execute" method will never be called:

***
{$mode delphi}
uses
  cthreads, classes, sysutils;

type
  tmythread = class(tthread)
    procedure execute;override;
  end;

procedure tmythread.execute;
begin
  writeln('executing');
end;

var
  c: tmythread;
begin
  writeln('creating thread suspended');
  c:=tmythread.create(true);
  sleep(500);
  writeln('resuming thread');
  c.resume;
  c.waitfor;
  c.free;
end.
***

Currently writes:
creating thread suspended
resuming thread
executing

With the patch, the last line is missing.

Secondly, ignoring this bug and suspending the thread inside itself:

***
{$mode delphi}
uses
  cthreads, classes, sysutils;

type
  tmythread = class(tthread)
    procedure execute;override;
  end;

procedure tmythread.execute;
begin
  suspend;
  writeln('executing');
end;

var
  c: tmythread;
begin
  writeln('creating thread suspended');
  c:=tmythread.create(false);
  sleep(500);
  writeln('resuming thread');
  c.resume;
  c.waitfor;
  c.free;
end.
***

Currently writes:
creating thread suspended
resuming thread
executing

With the patch:
creating thread suspended
executing
resuming thread

That barrier has nothing to do with "set values of variables before calling
the inherited create method to their own creation" (although it's not
entirely clear to me you mean by that). If you set values that the child thread will read after that thread has already been created, this memory barrier will not help either. That barrier is again about memory write ordering, which could cause the newly started thread to not see all writes
performed by the parent thread *before* creating the child thread.

Other than waiting for the values to be committed, I just don't see it's value.

The whole value is in waiting for the values to be committed. Without the write barrier, this could e.g. happen:

a) in parent thread
* globalvar:=1;
* create_thread();

b) in child thread:
writeln(gobalvar); // prints 0, or whatever the value of globalvar was before the parent thread assigned "1" to it

That can even happen on x86 in its default mode, because this is a "Stores reordered after Loads" situation (but as mentioned below, it's unlikely to happen).

And the reason that's it's probably not required, is because there's so much code in between that it's unlikely that any of those writes would still be outstanding at that point. It's not "for the few that don't understand how
to create a thread".

Exactly.  The other code being what?

If you mean the "code in between" by "the other code": any code executed between setting the global variable in the parent thread and the actual starting of the child thread (which includes all of the code in pthread_create, and in case of FPC in tthread.create and/or BeginThread, although in case of tthread.create there is also some extra communication between the parent thread and the child thread via the heap).


Jonas
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to