Path: utzoo!attcan!uunet!van-bc!ubc-cs!cheddar.ucs.ubc.ca!ballard From: ballard@cheddar.ucs.ubc.ca (Alan Ballard) Newsgroups: comp.os.os2.programmer Subject: Re: Horses! Message-ID: <9778@ubc-cs.UUCP> Date: 28 Sep 90 06:01:45 GMT References: <90270.152726TURGUT@TREARN.BITNET> Sender: news@cs.ubc.ca Reply-To: ballard@cheddar.ucs.ubc.ca (Alan Ballard) Organization: UBC Computing Centre, Vancouver, B.C., Canada Lines: 61 In article <90270.152726TURGUT@TREARN.BITNET> TURGUT@TREARN.BITNET (Turgut Kalfaoglu) writes: >... Here is the curiosity: if I put a >DosSleep(0L) in the main()'s loop where the beginthread is called five >times to create the five horses, everything is fine. If I remove that, >five horses are created, but they each receive the same index number (5), >and they move together too! (so only one horse appears on display). It >roughly looks like this: > >for (j=0;j<5;j++) { > if (_beginthread(horse,NULL,4096,&j) == 0) { > printf("Error"); > exit(1); > } > DosSleep(0L); >} >I remove the DosSleep and it no longer works! > >Any ideas? Is it a bug in OS/2 1.1 that got corrected with 1.2 ? Nope, its a bug in your version of the program. You're passing the address of the variable j. There are no guarantees about when the new processes will actually get to execute. Without the DosSleep, the main thread keeps running, for a while, and by the time the other threads get to pick up the parameter it has already changed back in the main thread. DosSleep with a parameter of zero gives the threads a chance to run for one time slice, so they pick up the value at that time and each get the appropriate value. To do this properly, you need to either pass the parameter by value, as it was in the original version or use semaphores to properly synchronize the startup so that each thread gets its parameter before the main thread goes on to start the next. Norton/LaFore's version of this program contains a C coding bug in the stack initialization, by the way (which may be the reason you switched to _beginthread?) The line stkptr = (int far *)malloc(STACK_SIZE) + STACKSIZE; should replaced with some variant of stkptr = (int far *)((char far *)malloc(STACK_SIZE) + STACK_SIZE); I've found Norton/LaFore good for getting the basic idea of the OS/2 kernel services, but it is rather casual about IPC issues in many of the multi-threaded processes. The requires synchronization is only done in places where it is the subject of the example; lots of other critical sections are really needed to make the programs behave as described. >Also I noticed that if the main() ends, even with DosExit(0,0), >all threads are killed, which is contrary to Peter Norton's book.. I seem to recall this was a change between 1.0 and 1.1 (or maybe between 1.1 and 1.2). When the main thread exits, all threads exit. Alan Ballard | Internet: ballard@ucs.ubc.ca University Computing Services | Bitnet: USERAB1@UBCMTSG University of British Columbia | Phone: 604-228-3074 Vancouver B.C. Canada V6R 1W5 | Fax: 604-228-5116