X-Authentication-Warning: delorie.com: mailnull set sender to djgpp-bounces using -f Message-ID: <0BA32251E589D2118EA60008C70DDCAB025F9187@JNJFRISEXS1.eu.jnj.com> From: "Baribaud, Christophe [JNJFR]" To: "'Eli Zaretskii'" , "Baribaud, Christophe [JNJFR]" Cc: djgpp AT delorie DOT com Subject: RE: multi-threading Date: Fri, 25 Jan 2002 07:49:47 +0100 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.5.2655.55) Content-Type: multipart/mixed; boundary="----_=_NextPart_000_01C1A56C.7AB04D30" Reply-To: djgpp AT delorie DOT com This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_000_01C1A56C.7AB04D30 Content-Type: multipart/alternative; boundary="----_=_NextPart_001_01C1A56C.7AB04D30" ------_=_NextPart_001_01C1A56C.7AB04D30 Content-Type: text/plain I don't succeed in sending messages to newsgroup including files ;-(( So I send it to you Here is the pre-alpha version of minimalistic multi-threading routines, if it is of some interest for anybody :-) Regards CB -----Message d'origine----- De : Eli Zaretskii [mailto:eliz AT is DOT elta DOT co DOT il] Envoye : jeudi 24 janvier 2002 11:17 A : Christophe BARIBAUD Cc : djgpp AT delorie DOT com Objet : Re: multi-threading On Thu, 24 Jan 2002, Christophe BARIBAUD wrote: > I am currently trying to build a minimalistic multi-threaded kernel with > djgpp. > When I change stack selector (ss) my programs hangs when calling __dpmi_int > It **seems** that DJGPP assumes SS=DS in order to function correctly. > > Can anybody confirm this ? Yes, the code produced by GCC assumes DS=SS=ES. If you change the SS to implement the multithreading, you will either have to find another way, or do that in assembly. ------_=_NextPart_001_01C1A56C.7AB04D30 Content-Type: text/html RE: multi-threading

I don't succeed in sending messages to newsgroup including files ;-((
So I send it to you

Here is the pre-alpha version of minimalistic multi-threading routines, if it is of some interest for anybody :-)

Regards
CB

-----Message d'origine-----
De : Eli Zaretskii [mailto:eliz AT is DOT elta DOT co DOT il]
Envoye : jeudi 24 janvier 2002 11:17
A : Christophe BARIBAUD
Cc : djgpp AT delorie DOT com
Objet : Re: multi-threading



On Thu, 24 Jan 2002, Christophe BARIBAUD wrote:

> I am currently trying to build a minimalistic multi-threaded kernel with
> djgpp.
> When I change stack selector (ss) my programs hangs when calling __dpmi_int
> It **seems** that DJGPP assumes SS=DS in order to function correctly.
>
> Can anybody confirm this ?

Yes, the code produced by GCC assumes DS=SS=ES.

If you change the SS to implement the multithreading, you will either
have to find another way, or do that in assembly.

  ------_=_NextPart_001_01C1A56C.7AB04D30-- ------_=_NextPart_000_01C1A56C.7AB04D30 Content-Type: application/octet-stream; name="TASK.C" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="TASK.C" #include // Just for thread sample #include // Just for thread sample /* ** Simple non-preemptive multi-tasking routines v0.0 ** Christophe BARIBAUD (cbaribau AT jnjfr DOT jnj DOT com) ** Jan 2002 ** ** This is a **draft** ** These routines have been tested under MS-DOS 6.22 and Windows 2000 ** using DJGPP v2.03 */ // MAX_THREAD : maximum number of threads // It may have any value, but the actual stack space of any thread // is _stklen/MAX_THREAD // This implementation doesn't check stack overflow, so be careful... #define MAX_THREAD 4 struct InternalThread { char *sp; // Stack pointer of thread int status; // 0 =3D free, 1 =3D running }; extern long _stklen; // Size of stack allocated by DJGPP, may be = changed struct InternalThread InternalThreadTable[MAX_THREAD]; int CurrentThread; // Globals needed to communicate with assembler part char *Yield_vesp; char **Yield_esp; void (*Yield_start)(void); // // InitializeThreads // // This routine must be called before any call to thread routines // void InitializeThreads(void) { // First of all, let retreive existing stack space asm("movl %ss,_Yield_vesp"); // get current stack selector into = Yield_vesp //printf("Stack selector : %lx\r\n",Yield_vesp); unsigned short buffer[4]; if (__dpmi_get_descriptor(Yield_vesp,(void*)buffer) =3D=3D -1) { printf("Unable to retieve stack selector informations\r\n"); exit(-1); } // Now we compute segment limit. Cf. dpmi documentation unsigned long StackSize =3D buffer[0]; // segment limit field StackSize |=3D ((buffer[3] & 0x000F)<<16); // 4 high order bits if ((buffer[3] & 0x0080) !=3D 0) // page granular StackSize =3D StackSize << 12; printf("Total stack space : = [%lx:%lx]\r\n",StackSize-_stklen,StackSize); // Stack space is between StackSize-_stklen and StackSize int i; for (i=3D0;isp; t->status =3D 1; // new thread is supposed to be alive... // printf("Task stack entry : %lx\r\n",Yield_vesp); =20 Yield_start =3D start; Yield_esp =3D &InternalThreadTable[CurrentThread].sp; CurrentThread =3D i; // SwitchTaskJump jumps into new thread SwitchTaskJump(); return i; } // // Yield // // This routine yields control to next running thread // It should be used when a thread waits for an event (keyboard, com, = ...) // and sometimes during long operations // Sadly, it is not possible to insert it in DOS wait operations like = disk access // void Yield(void) { struct InternalThread *from,*to; from =3D &InternalThreadTable[CurrentThread]; to =3D 0; int i; for (i=3D0;isp; Yield_vesp =3D to->sp; SwitchTask(); // switch! } // // KillMyThread // // Nobody is supposed to call this routine directly // It is called when a thread returns from its start routine // Then, current thread is deleted // void KillMyThread(void) { // If I got there, a thread returns from its start function if (CurrentThread =3D=3D 0) { printf("PANIC : trying to kill main thread\r\n"); exit(-1); } //printf("Thread %d is dying...\r\n",CurrentThread); InternalThreadTable[CurrentThread].status =3D 0; // current thread is = dead Yield(); // resume another thread } void thread1(void) // thread sample 1 { int i; for (i=3D0;i<1000;i++) { printf("Thread 1 : %d %f\r\n",i,cos(i)); Yield(); } } void thread2(void) // thread sample 2 { int i; for (i=3D0;i<10;i++) { printf("Thread 2 : %d %f\r\n",i,sin(i)); Yield(); } } // Demo program int main() { InitializeThreads(); // Needed before any call to thread routines CreateThread(thread1); CreateThread(thread2); int i; for (i=3D0;i<30;i++) // Loops 30 times threads and exit { printf("Main thread\r\n"); Yield(); } } ------_=_NextPart_000_01C1A56C.7AB04D30 Content-Type: application/octet-stream; name="TASKASM.S" Content-Disposition: attachment; filename="TASKASM.S" /* ** Simple non-preemptive multi-tasking routines v0.0 ** Christophe BARIBAUD (cbaribau AT jnjfr DOT jnj DOT com) ** Jan 2002 ** Assembler part : save context, restore context and juggle with ** stack pointer */ .globl _SwitchTask _SwitchTask: pushl %eax pushl %ebx pushl %ecx pushl %edx pushl %ebp pushl %edi pushl %esi movl _Yield_esp,%eax movl %esp,(%eax) movl _Yield_vesp,%esp popl %esi popl %edi popl %ebp popl %edx popl %ecx popl %ebx popl %eax ret .globl _SwitchTaskJump _SwitchTaskJump: pushl %eax pushl %ebx pushl %ecx pushl %edx pushl %ebp pushl %edi pushl %esi movl _Yield_esp,%eax movl %esp,(%eax) movl _Yield_vesp,%esp call *_Yield_start call _KillMyThread ------_=_NextPart_000_01C1A56C.7AB04D30--