Amiga.org
Operating System Specific Discussions => Amiga OS => Amiga OS -- Development => Topic started by: Slash on August 31, 2004, 09:27:56 PM
-
f I create a new process from my main program thread, using CreateNewProcTags, do I therefore have to open any libraries my new process may need by opening them again in the new process, or are they inherited from the parent process?
More specifically, every library call I'm using (DOS, graphics etc.) works, apart from bsdsocket.library calls.
Thanks for any help,
Daniel
-
It's always been my understanding that a complete program, which may contain several concurrent threads can all share resources declared within that program* (including library bases etc).
I've never had to open a library for a process created by my main task and never encountered any problems as a consequence.
Just make sure you properly (Semaphore) protect any resouces such as IO handles etc. that you intend to share between threads and all should be OK.
*scope permitting of course ;-)
-
Thanks Karlos, I must be doing something else wrong to stop my socket calls working... I'll investigate further. :-)
-
Yup, you can share just about any library pointer between processes.
In the Miami documentation anyway, they do mention that you can't share bsdsocket.library the same way, though. Multiple calls to bsdsocket in the same program will cause a crash, although the reason escapes me.
You just have to be mindful that when you design Internet applications, you need to do all of the socket stuff in its' own process and close SocketBase when you're done. It's probably the most sensible design to spawn your download/upload process like a 'worker thread' that signals or msgs the main task when it's done or whenever the progress level changes.
Probably one of the hardest lessons I've had to learn anyway... :pissed:
-D00kie
-
"More specifically, every library call I'm using (DOS, graphics etc.) works, apart from bsdsocket.library calls."
Every process using bsdsocket.library must open that library on its own. Sharing bsdsocketbase is not permitted.
-
"Although in most cases it is possible for a parent task to pass a library base to a child task so the child can use that library , for some libraries , this is not possible. For this reason, the only library base sharable between tasks is Exec's library base."
RKM: Libraries 3rd Edition, chapter Exec Tasks, page 467
-
@Jose
This "only-exec" rule is broken all over, and it's common practice to share library bases, except those explicitly known to be non-shareable. Typically at least all standard system libraries are considered shareable.
About bsdsocket.library
One of the special non-shareable libraries is bsdsocket.library. One of the reasons is that each process needs to maintain certain set of static data about the network stack, and it would be really inefficient if each library function would need to lookup caller task context from some list or array (ok, it could use hashtable or btree). Instead each opener task gets unique librarybase with unique static data in possize and (back)ptr to global base/data (the one found from system LibList). This way no lookup is needed and each function can access the local data directly.
-
Nice to know. It's also good for lazy people like me 8-)
-
I think Piru is right and nobody cares about this rule.
However I belive the rule is a rule and should be kept.
It is not that hard in this case.
Generally speaking tasks should share the same address space, while processes not, and at least for that reason libraries should be reopened personally by each process.
Because people are not respecting such rules it is not possible to introduce memory protection mechanisms to the system.
Cheers for Jose for reminding RKRMs! :pint:
-
Hmm.
I have been breaking this rule for ages then :-D
My C++ (AmigaOS version) layer uses a struct Process in its Threadable service class implementation rather than a Task since it is not possible to know (from the implementation point of view) which Threadable objects created by the programmer will use what other resources with their internal thread.
Every Threadable object shares resources opened by the main thread and is capable of sharing resources allocated by its internal thread with others (there is a Lockable service class that uses Semaphores for this).
The system ensures no Threadable object can outlive the thread that created it.
What I can see is that instead of Processes, I should be using Tasks. Unfortunately, IIRC Tasks can't cant call dos.library or anything which in turn woild call dos.library, which is the whole reason I used Process in the first place :-/
-
Unfortunately, IIRC Tasks can't cant call dos.library or anything which in turn woild call dos.library
You can call DOS functions from a task if they don't need process structure (file I/O). Those DOS functions which need a process structure are protected against tasks.
-
Those DOS functions which need a process structure are protected against tasks.
Well, for example SetIoErr() is not, and various other parts of dos.library call it. So it's a bit risky to call functions from within a task, you risk trashing some memory past struct Task.
-
Piru wrote:
Those DOS functions which need a process structure are protected against tasks.
Well, for example SetIoErr() is not, and various other parts of dos.library call it. So it's a bit risky to call functions from within a task, you risk trashing some memory past struct Task.
I once tried using Tasks for my needs but (for the reasons I already gave) it was a total disaster. If, and only if, your Threadable object does not use any IO (and that means interacting with any other objects that do via its internal thread) did it work. That then spawned (pun unintentional) the idea of LightThreadable and Threadable (the former using a Task in it's implementation). For something ultimately meant to make programming simpler and more flexible it was rather self defeating :-)
So in the end, I settled for a generic Threadable class that internally uses a Process.