From: cknight AT nmt DOT edu (Chris-top-her) Newsgroups: comp.os.msdos.djgpp Subject: Help w/ Interrupts Date: 17 Oct 1997 22:06:58 GMT Organization: New Mexico Institute of Mining and Technology, Socorro NM Lines: 222 Message-ID: <628ni2$dct$1@newshost.nmt.edu> NNTP-Posting-Host: rust.nmt.edu Summary: Timer interrupt help needed Keywords: timer, interrupt, PM, 2.01, To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Precedence: bulk hello all, I'm looking for little help with some code I'm writing. I'm attempting to implement coroutines using DJGPP, w/ csdpmi as my dpmi server. I am able to do a manual call to my sched routine and everything is fine, but if I try to set it as the fn to call when a timer interrupt happens the program dies on me. The best I've been able to do is get 1 manual call, and 1 interrupt call to sched. I've read through the faq on interrupts, and the problem I'm having seems no clearer. Any help would be appreciated. I include source below. Thanks, Chris Knight cknight AT nmt DOT edu Note this is not all the code, just what I thought pertainent. If you need more let me know. ------------------------timer functions ------------------------------ void my_int() { sched(); /* this doesn't work */ /* int_counter++; */ /* but this does */ } void NewTimerInt() { _go32_dpmi_get_protected_mode_interrupt_vector(8,&old_handler); new_handler.pm_offset = (unsigned) my_int; new_handler.pm_selector = _go32_my_cs(); _go32_dpmi_chain_protected_mode_interrupt_vector(8,&new_handler); printf("Original 1c = 0x%X\n",old_handler.pm_offset); printf("New 1c offset = 0x%X\n",new_handler.pm_offset); printf("New 1c selector = 0x%X\n", new_handler.pm_selector); printf("Done with NewTimerInt()\n"); } --------------------- include file ---------------------------- #include #include #include #include #include #include #include #include #include #define NUMBEROFROUTINES 10 #define STACKSIZE 1000 /*handler structs for old timer int, and new chained timer int */ _go32_dpmi_seginfo old_handler, new_handler; volatile int int_counter; volatile int sched_count; /* coroutine status */ #define RUNNABLE 1 #define WAITING 0 /*#define DEBUG */ typedef struct Coroutine{ unsigned long sp; unsigned long bp; unsigned long ax; unsigned long bx; unsigned long cx; unsigned long dx; unsigned long si; unsigned long di; unsigned long fl; unsigned short cs; unsigned short ds; unsigned short es; unsigned short fs; unsigned short gs; unsigned short ss; unsigned long *stack; int status; } coroutine; typedef struct Qnode{ coroutine *data; struct Qnode *next; } qnode; extern coroutine* current; extern qnode* q; void init_functions(); void exit_init(); void make_runable(coroutine *); coroutine* new_coroutine(void *); void sched(); int save(); int resume(); void add_to_queue(coroutine *); void remove_from_queue(coroutine *); void my_int(); ----------------------------------------------------------------------- coroutine *new_coroutine(void *coroutine_address) { coroutine *new; disable_ints(); /* printf("here I am in newcoroutine()\n"); */ new = (coroutine *)malloc(sizeof(coroutine)); new->stack = (unsigned long *)malloc(sizeof(unsigned long)* STACKSIZE); new->sp = new->bp = (unsigned long) (&new->stack[STACKSIZE]); new->pc = (unsigned long) coroutine_address; new->cs = get_cs() ; new->ds = new->es = new->ss = get_ds() ; new->fs = get_fs() ; new->gs = get_gs() ; new->fl = get_flags() ; new->status = WAITING; add_to_queue(new); enable(); return new; } void sched() { disable_ints(); if(save()) /* You are expected to understand this */ { sched_count++; current = next_function(); resume(); enable_ints(); } enable_ints(); return; } int save() { if (q != NULL) return _save(); return 0; } int resume() { return _resume(); } --------------------------------------------------------------------------- .global __resume __resume: call _disable_ints pushl %ebp movl %esp, %ebp # copy stack pointer movl _current,%eax movl 0x4(%eax),%esp pushl 0x24(%eax) # get flags from current popfl # push them in the right place movw 0x32(%eax),%ss # dont do any more pushes after this movw 0x30(%eax),%gs # until we get a new stack movw 0x2E(%eax),%fs movw 0x2C(%eax),%es movw 0x2A(%eax),%ds # save cs for last movl 0x20(%eax),%edi movl 0x1C(%eax),%esi movl 0x18(%eax),%edx movl 0x14(%eax),%ecx movl 0x10(%eax),%ebx # screw eax, its a return value (0) movl 0x8(%eax),%ebp movl 0x4(%eax),%esp # put new coroutine stack in place addl $4,%esp # Throw out that stupid return address pushfl # pushw 0x28(%eax) # Push the %cs on the stack pushl 0x0(%eax) # And the return address we want xorl %eax,%eax # always fail call _enable ret .global __save __save: pushl %ebp movl %esp, %ebp # copy stack pointer movl _current,%eax # put address of current for filling pushl 0x4(%ebp) # get return address popl 0x0(%eax) # put it first in current movl %esp, 0x4(%eax) movl %ebp, 0x8(%eax) movl %eax, 0xC(%eax) movl %ebx, 0x10(%eax) movl %ecx, 0x14(%eax) movl %edx, 0x18(%eax) movl %esi, 0x1C(%eax) movl %edi, 0x20(%eax) pushfl # put flags on stack popl 0x24(%eax) # now put them in current movw %cs, 0x28(%eax) movw %ds, 0x2A(%eax) movw %es, 0x2C(%eax) movw %fs, 0x2E(%eax) movw %gs, 0x30(%eax) movw %ss, 0x32(%eax) movl $1,%eax # save always succeeds movl %ebp, %esp popl %ebp ret