Dear All! As I have already read in archives, thread support in GPC is missing now. I know that I can "feel free to implement it myself" but, unfortunately, I am rather a compiler user than a creator, I'm not a such guru (at least, for the time being). Anyway, I've already built the program in GPC using pthreads library (using modules on C as an interface to pthreads library) and it works (at first glance). As far as I know, one of the potential damages with multithreaded programs written in GPC is working with files, isn't it? Would you please clarify me other issues (potential damages) of such kind to avoid them from the program or at least to know about them? I mean such kinds of activity which use global (system) variables that are not synchronized, etc. And another question: is it possible to use in some way pthread datatypes in GPC Pascal programs? For example, is it possible to define variable of type pthread_mutex_t in Pascal program? I know how to export variable from C unit or library, but is it possible to export datatype or anything like that? Thank you, Igor Marnat marny@rambler.ru
Igor Marnat wrote:
synchronized, etc. And another question: is it possible to use in some way pthread datatypes in GPC Pascal programs? For example, is it possible to define variable of type pthread_mutex_t in Pascal program? I know how to export variable from C unit or library, but is it possible to export datatype or anything like that?
It is, but I would not recommend to do so. Instead, I'd recommend to just port the functions from pthread.h (i.e. give them an "external" declared header in your unit) and handle the pthread_mutex_t just as a pointer.
However, I'm currently working on a (pthread-based) standard unit for GPC multithreading, so if you aren't in a hurry, maybe I can offer you a solution within a few weeks. :-)
Yours,
Markus
Hello Markus, Frank, Peter.
Thank you for your answers, I'm fully satisfied:)
MG> It is, but I would not recommend to do so. Instead, I'd recommend to just port MG> the functions from pthread.h (i.e. give them an "external" declared header in MG> your unit) and handle the pthread_mutex_t just as a pointer.
It is really the way to go, I'll use it. But just I'm curious: how can I export complex datatype from C units since it is possible?
MG> However, I'm currently working on a (pthread-based) standard unit for GPC MG> multithreading, so if you aren't in a hurry, maybe I can offer you a solution MG> within a few weeks. :-)
I'll be waiting for it and I'll be beta-tester surely. Shall we know about its readiness from mailing-list?
Best regards, Igor Marnat mailto:marny@rambler.ru
Igor Marnat wrote:
MG> It is, but I would not recommend to do so. Instead, I'd recommend to just MG> port the functions from pthread.h (i.e. give them an "external" declared MG> header in your unit) and handle the pthread_mutex_t just as a pointer. It is really the way to go, I'll use it. But just I'm curious: how can I export complex datatype from C units since it is possible?
There are several ways to do so.
If you want to port, for example, a C struct, the simplest (but also most error-prone) way is to re-model it 1:1 as a Pascal record and insert it in every function declaration o.s. where it appears. E.g. if there is a struct
typedef struct { int i; double x; char *name; } foo;
and a function
void bar(foo a_foo);
you can "translate" it in your own Pascal sources by defining something like
type tFoo = record i: integer; x: double; name: CString; end;
Procedure bar(aFoo: tFoo); attribute (name = 'bar'); external;
This is an easy way, but it relies on the Pascal record and its member variables having exactly the same size as the C struct and its members. So this way will work as long as 1.) the primitive data types like integer, double etc. are really equivalent to their C siblings and 2.) the definition of struct foo isn't changed at some point when the used C API changes. But if only they change the sequence of two member variables for whatever reason, you're in trouble.
To avoid this, I usually encapsulate the struct as an object instead of a record:
type tFoo = object public Constructor init; Destructor fini; virtual; Function i: integer; Function x: double; Function name: CString; private fNativeFoo: pointer; end;
...
Function cCreateFoo: pointer; attribute (name = 'c_create_foo'); external; Procedure cFreeFoo(aFoo: pointer); attribute (name = 'c_free_foo'); external; Function cFooGetI(aFoo: pointer); attribute (name = 'c_foo_get_i'); external; ...
Constructor tFoo.init; begin fNativeFoo:= cCreateFoo; end;
Destructor tFoo.fini; begin cFreeFoo(fNativeFoo); end;
Function tFoo.i = result: integer; begin result:= cFooGetI(fNativeFoo); end;
...
You'll need to write an additional C file then to define your external functions:
foo* c_create_foo () { return new foo; }
void c_free_foo(foo *a_foo) { free(a_foo); }
int c_foo_get_i(foo *a_foo) { return a_foo -> i; }
...
This is, at a first glance, a lot more work than just "translating" the struct, but you can always be sure that your object remains a valid port of the struct, no matter what member variables they add in the API afterwards and where.
So far for structs. ;-) As for enumeration types, I would always port them as their Pascal equivalent, i.e. if you've got something like
typedef enum {foo, bar, baz, ...} pruzzel;
just make it a
type pruzzel = (foo, bar, baz, ...);
Adapting this one to a possible API change is a lot less work than e.g. with structs. (And it usually occurs far less frequently.)
As for all other complex C data types (like, e.g. pthreads or mutexes), I'd always work with pointers to them, treat them as untypified pointers in the Pascal sources and implement the last access layer in C.
MG> However, I'm currently working on a (pthread-based) standard unit for GPC MG> multithreading, so if you aren't in a hurry, maybe I can offer you a MG> solution within a few weeks. :-) I'll be waiting for it and I'll be beta-tester surely. Shall we know about its readiness from mailing-list?
Yes, I'll announce when it's ready so far. But as I said, it'll certainly take a few weeks. The unit will be part of a larger GPC programming framework, and there's quite some foundation work to be done in some other units before I can go on to the thread unit.
Best,
Markus
Hi Markus! Thank you for detailed explanation. Shortly speaking, there are no possibility to export datatype from C unit (speaking in terms of really export) - it's possible only
1. to make its copy in Pascal unit and maintain there correspondence manually or 2. to use the pointers
Well, both possibilities are acceptable. Thank you, best regards, Igor Marnat mailto:marny@rambler.ru
Igor Marnat wrote:
As I have already read in archives, thread support in GPC is missing now. I know that I can "feel free to implement it myself" but, unfortunately, I am rather a compiler user than a creator, I'm not a such guru (at least, for the time being).
The good news is that most critical part are in the RTS which is more or less normal Pascal (mostly) and C (a bit) code. Just look for global variables etc. there.
As far as I know, one of the potential damages with multithreaded programs written in GPC is working with files, isn't it?
Yes, that's one global variable (_p_FDRList) that's only used in open/close operations (and perhaps a few more). The file structures itself should be no problem (unless two threads access the same file at once, but that's the same problem for every variable; and unless the OS itself is not thread-safe WRT files, but this shouldn't be a problem today I suppose ;-).
Would you please clarify me other issues (potential damages) of such kind to avoid them from the program or at least to know about them? I mean such kinds of activity which use global (system) variables that are not synchronized, etc.
I haven't looked into it, but if it's easy to add synchronization code to the RTS without making it *dependent* on threads, as you said, feel free to do it. :-)
Frank
As I have already read in archives, thread support in GPC is missing now. I know that I can "feel free to implement it myself" but, unfortunately, I am rather a compiler user than a creator, I'm not a such guru (at least, for the time being).
The good news is that most critical part are in the RTS which is more or less normal Pascal (mostly) and C (a bit) code. Just look for global variables etc. there.
Is there any thread safe issues if the no RTS units are included specifically? We use GPC for a heavily threaded application that has been shipping for some time and have never had any problems, but it is Mac OS X only and we don't use any of the RTS except that built in to the compiler.
Is there something I should be worrying about? Peter.
Peter N Lewis wrote:
As I have already read in archives, thread support in GPC is missing now. I know that I can "feel free to implement it myself" but, unfortunately, I am rather a compiler user than a creator, I'm not a such guru (at least, for the time being).
The good news is that most critical part are in the RTS which is more or less normal Pascal (mostly) and C (a bit) code. Just look for global variables etc. there.
Is there any thread safe issues if the no RTS units are included specifically? We use GPC for a heavily threaded application that has been shipping for some time and have never had any problems, but it is Mac OS X only and we don't use any of the RTS except that built in to the compiler.
As I said, files use a few global variables. Other parts (also used automatically by the compiler) might, but I've never checked them.
I've also never checked the compiler generated code for such cases. Initializers use global flags, but since I suppose threading usually starts after initializers are run, this should be no problem.
Frank
Frank Heckenbach wrote:
As I said, files use a few global variables. Other parts (also used automatically by the compiler) might, but I've never checked them.
I've also never checked the compiler generated code for such cases. Initializers use global flags, but since I suppose threading usually starts after initializers are run, this should be no problem.
Any thoughts on what makes the gpc runtime library kernel-safe or kernel-unsafe ? I assume --no-exceptions is on by default in gpc ?
Regards,
Adriaan van Os
Adriaan van Os wrote:
Frank Heckenbach wrote:
As I said, files use a few global variables. Other parts (also used automatically by the compiler) might, but I've never checked them.
I've also never checked the compiler generated code for such cases. Initializers use global flags, but since I suppose threading usually starts after initializers are run, this should be no problem.
Any thoughts on what makes the gpc runtime library kernel-safe or kernel-unsafe ? I assume --no-exceptions is on by default in gpc ?
Kernel-safe!? Do you mean you want to implement a kernel in GPC using the runtime library? I don't think that's a way to go, since the runtime is much more high-level -- e.g., it uses files while the kernel must implement files on the lowest level; also the floating point (including complex) routines should not be useful for a kernel where FP is usually avoided; etc.
This doesn't mean that the Pascal compiler itself couldn't be used to compile a kernel, but that's a situation where it's probably better to start with a different, minimal runtime library.
Frank
Frank Heckenbach wrote:
Kernel-safe!? Do you mean you want to implement a kernel in GPC using the runtime library?
Just a small "Hello Kernel" kernel extension, out of curiosity.
I don't think that's a way to go, since the runtime is much more high-level -- e.g., it uses files while the kernel must implement files on the lowest level; also the floating point (including complex) routines should not be useful for a kernel where FP is usually avoided; etc.
This doesn't mean that the Pascal compiler itself couldn't be used to compile a kernel, but that's a situation where it's probably better to start with a different, minimal runtime library.
Ah, I see, thanks for this information.
Regards,
Adriaan van Os
Adriaan van Os wrote:
Frank Heckenbach wrote:
Kernel-safe!? Do you mean you want to implement a kernel in GPC using the runtime library?
Just a small "Hello Kernel" kernel extension, out of curiosity.
A kernel extension -- well, I only know about the Linux kernel, but you usually #include a number of kernel specific headers (which contain asm code, special #defines and other nontrivial stuff). Trying to translate them to Pascal might not be really nice unless we have a fully automatic header converter that also handles such constructs ...
Frank
Frank Heckenbach wrote:
A kernel extension -- well, I only know about the Linux kernel, but you usually #include a number of kernel specific headers (which contain asm code, special #defines and other nontrivial stuff). Trying to translate them to Pascal might not be really nice unless we have a fully automatic header converter that also handles such constructs ...
I often have to translate C headers -- and I am sure I am not alone. What I do, is I open a Pascal interface unit and then translate whatever I need, I don't translate all of it. This is a bit tedious, but at least it can be done. The situation is much worse when the system software or some plug-in architecture forces you to use C++ or Objective-C.
Yes, a fully automatic C header converter would be highly useful tool.
Regards,
Adriaan van Os
On 18 Jun 2004 at 15:17, Frank Heckenbach wrote:
Adriaan van Os wrote:
Frank Heckenbach wrote:
Kernel-safe!? Do you mean you want to implement a kernel in GPC using the runtime library?
Just a small "Hello Kernel" kernel extension, out of curiosity.
A kernel extension -- well, I only know about the Linux kernel, but you usually #include a number of kernel specific headers (which contain asm code, special #defines and other nontrivial stuff). Trying to translate them to Pascal might not be really nice unless we have a fully automatic header converter that also handles such constructs ...
Perhaps I am just being naïve/ignorant - but wouldn't it be possible to (somehow) compile the C headers into an intermediate (.gpi or .o or .whatever) file that GPC can use? We already have {$L foo.c} which calls the C compiler to produce an object file. Isn't there a way of extending this concept with header files?
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof A Olowofoyeku (The African Chief) wrote:
On 18 Jun 2004 at 15:17, Frank Heckenbach wrote:
Adriaan van Os wrote:
Frank Heckenbach wrote:
Kernel-safe!? Do you mean you want to implement a kernel in GPC using the runtime library?
Just a small "Hello Kernel" kernel extension, out of curiosity.
A kernel extension -- well, I only know about the Linux kernel, but you usually #include a number of kernel specific headers (which contain asm code, special #defines and other nontrivial stuff). Trying to translate them to Pascal might not be really nice unless we have a fully automatic header converter that also handles such constructs ...
Perhaps I am just being naïve/ignorant - but wouldn't it be possible to (somehow) compile the C headers into an intermediate (.gpi or .o or .whatever) file that GPC can use? We already have {$L foo.c} which calls the C compiler to produce an object file. Isn't there a way of extending this concept with header files?
Substantial parts of such headers are macro #defines which can't be (and IMHO shouldn't be) stored in GPI files.
For regular declarations, it may be just as easy/hard to convert them to Pascal declarations (i.e., header translator) and compile them, as to compile C declarations to GPI files directly, and the former seems to be somewhat more flexible.
Frank
Dear All! After I've cleared for me the questions about complex datatypes import from C units, I would like to clear the question about C system constants import. Details: I would like to use in my program Unix system log functionality. It uses some C constants in syslog call (for example, importance level - LOG_NOTICE, LOG_EMERG, LOG_ALERT, etc...). Pedantically speaking, they are not the constants but rather C preprocessor definitions. So I've wrote the wrapper for syslog function like:
void LogMessage (int Priority, char* MessagePtr) { openlog ("[LOG_PROGRAM]", 0, LOG_LOCAL0); syslog (Priority, MessagePtr); return; }
where Priority may be one of LOG_NOTICE, LOG_EMERG, LOG_ALERT, etc... (as it's defined in "man 3 syslog").
Then I've made an import in my Pascal unit like:
procedure LogMessage (Priority: integer; MessagePtr: PChar); asmname 'LogMessage';
But how can I get these values of C preprocessor definitions in my Pascal program? The only way I can invent, is to define variables in C unit, assign them appropriate values and import these variables in Pascal unit. Not pretty good, really. Regards, Igor Marnat mailto:marny@rambler.ru
On Friday 18 June 2004 15:40, Igor Marnat wrote:
But how can I get these values of C preprocessor definitions in my Pascal program?
Please note, that "asmname" is deprecated.
In C
int foo = FOO_CONST;
where FOO_CONST is defined somewhere else.
In Pascal:
var MyFoo: Integer; attribute (name='foo') ; external; (untested)
Eike
On Fri, Jun 18, 2004 at 03:54:39PM +0200, Eike Lange wrote:
On Friday 18 June 2004 15:40, Igor Marnat wrote:
But how can I get these values of C preprocessor definitions in my Pascal program?
Please note, that "asmname" is deprecated.
In C
int foo = FOO_CONST;
where FOO_CONST is defined somewhere else.
In Pascal:
var MyFoo: Integer; attribute (name='foo') ; external; (untested)
Eike
Better yet:
const int foo = FOO_CONST;
var MyFoo: Integer; attribute (name = 'foo', const, external); ^^^^^
Then the compiler treats the variable as constant, so it can't be modified in the Pascal code by accident.
Emil Jerabek
Emil Jerabek wrote:
On Fri, Jun 18, 2004 at 03:54:39PM +0200, Eike Lange wrote:
On Friday 18 June 2004 15:40, Igor Marnat wrote:
But how can I get these values of C preprocessor definitions in my Pascal program?
Please note, that "asmname" is deprecated.
In C
int foo = FOO_CONST;
where FOO_CONST is defined somewhere else.
In Pascal:
var MyFoo: Integer; attribute (name='foo') ; external; (untested)
Better yet:
const int foo = FOO_CONST;
var MyFoo: Integer; attribute (name = 'foo', const, external); ^^^^^
Then the compiler treats the variable as constant, so it can't be modified in the Pascal code by accident.
Alternative:
Pascal:
const foo = 42; { whichever value you choose }
C:
#define foo 42 /* same value as in Pascal */
void LogMessage (int Priority, char* MessagePtr) { [...] syslog (Priority == foo : FOO_CONST ? Priority == bar : BAR_CONST ? ... , MessagePtr); }
Hope you get the idea.
Then you have a constant in Pascal (but not necessarily the same value as FOO_CONST in C).
Frank
EL> Please note, that "asmname" is deprecated.
Yes, but I'm forced to use it for ARM compilations because recent version of GPC doesn't function very well (I can't compile it together with arm-elf toolchain).
EL> where FOO_CONST is defined somewhere else.
EL> var EL> MyFoo: Integer; attribute (name='foo') ; external; EL> (untested)
So, it's possible using variables only. Ok, thank you!