Presentation is loading. Please wait.

Presentation is loading. Please wait.

William Sandqvist Övning 9 Trådar och Semaforer.

Similar presentations


Presentation on theme: "William Sandqvist Övning 9 Trådar och Semaforer."— Presentation transcript:

1 William Sandqvist Övning 9 Trådar och Semaforer

2 William Sandqvist Digitala komponenter Assemblerprogram C In- och utmatning Avbrott och "trap" Cacheminnen Trådar, synkronisering DC F1 DC F2 CE F1 CE F3 CE F4 CE F5 CE F6 CE F7 CE F8 CE F9 CE F10 CE F2 DC Ö1 DC Ö2 CE Ö4 CE Ö1 CE Ö2 CE Ö3 CE Ö10 CE Ö7 CE Ö8 CE Ö9 CE Ö5CE Ö6 lab dicom lab nios2time hemlab C lab nios2io lab nios2int hemlab cache hemlab trådar tentamen Datorteknik & komponenter

3 William Sandqvist Kommer ni ihåg: Reella tal Decimalkomma ”,” och Binärpunkt ”.” 10, =

4 William Sandqvist IEEE – 32 bit float Dec  IEEE-754 Genom att exponenteten skrivs exess–127 kan flyttal storlekssorteras med vanlig heltalsaritmetik!

5 William Sandqvist 9.1 Maskinaritmetik IEEE 32 bit flyttal s eeeeeeee fffffffffffffffffffffff C Vad blir: +1,5625  2 2 = +6,

6 William Sandqvist

7 William Sandqvist Programvaran till Hemlab 3

8 William Sandqvist Allt kan inte skrivas i C.  Med C kan man inte nå namngivna register ( register betyder bara en rekommendation att använda något register)  Med C kan man inte styra vilken instruktion som ska användas  Med C kan man inte styra var i minnessegmenten variabler placeras (men man kan använda adress- operatorn & för att undersöka var variablerna hamnar)

9 William Sandqvist (Primtal är bra testverktyg) Räkna primtal. En algoritm som prövar talen i ordning och ”producerar” primtalen är en bra ”pseudoslump”-generator. Primtalstätheten minskar ju större tal man undersöker, så med startvärdet kan man styra hur ofta primtal- en skall produceras. (Primtalskunskap ingår naturligtvis inte i kursen).

10 William Sandqvist Producer/Consumer (primtal)

11 William Sandqvist Timesharing, trådar delar på en CPU

12 William Sandqvist Timeravbrott och trådbyte

13 William Sandqvist Timer_1 tick # Initialize timer_1. movia r8,de2_timer_1_base movia r9,de2_timer_1_timeout_value srli r10,r9,16 stw r10,12(r8) # Write periodh andi r10,r9,0xffff stw r10,8(r8) # Write periodl movi r10,7 # start, cont, ito stw r10,4(r8) oslab_lowlevel_asm.s Var har Du sett det här förut?

14 William Sandqvist Yield ( trap -instruktion) och trådbyte

15 William Sandqvist oslab_yield() Trap-instruktionen kan man man inte nå från C. Därför gör man en assemblerfunktion med trap- instruktionen att anropa från C (”Wrapper”, ett paket)..global oslab_yield oslab_yield: trap ret void oslab_yield( void); oslab_lowlevel_asm.s

16 William Sandqvist oslab_begin_critical_region() Disable interrupt, nollställa PIE-biten i status-registret, kan man man inte nå från C. Därför gör man en assemblerfunktion att anropa från C (”Wrapper”, ett paket)..global oslab_begin_critical_region oslab_begin_critical_region: wrctl status,r0 ret void oslab_begin_critical_region( void); oslab_lowlevel_asm.s

17 William Sandqvist oslab_end_critical_region() Enable interrupt, ettställa PIE-biten i status-registret, kan man man inte nå från C. Därför gör man en assemblerfunktion att anropa från C (”Wrapper”, ett paket)..global oslab_end_critical_region oslab_end_critical_region: movi r8,1 wrctl status,r8 ret void oslab_end_critical_region( void); oslab_lowlevel_asm.s

18 William Sandqvist oslab_exeption_handler timeslicesyield oslab_lowlevel_asm.s

19 William Sandqvist oslab_exeption_handler oslab_exception_handler: rdctl et,estatus # Check ESTATUS andi et,et,1 # Test EPIE beq et,r0,oslab_exception_was_not_an_interrupt rdctl et,ipending # Check IPENDING beq et,r0,oslab_exception_was_not_an_interrupt # If control comes here, we have established that the # exception was caused by an interrupt. # Possible source Timer_1... oslab_exception_was_not_an_interrupt: # Possible source trap-instruction (YIELD)... Var har Du sett det här förut? oslab_lowlevel_asm.s

20 William Sandqvist Trådarnas kod, data, och stack

21 William Sandqvist Trådarnas data och stack #include #include "oslab_lowlevel_h.h" int NextPrime( int ); #define FIFO_SIZE 10 struct Prod { int startvalue; int id; }; unsigned int stack1[0x400]; /* Stack for thread 1 */ unsigned int stack2[0x400]; /* Stack for thread 2 */ unsigned int stack3[0x400]; /* Stack for thread 3 */ unsigned int stack4[0x400]; /* Stack for thread 4 */ unsigned int stack5[0x400]; /* Stack for thread 5 */ oslab_main.c Varje tråd har en egen stack Trådarna har egna dataposter (struct)

22 William Sandqvist Fifo-kö, och semaforer oslab_main.c int Fifo[FIFO_SIZE]; /* Array holding FIFO queue data. */ int rdaddr; /* Next unread entry when reading from queue. */ int wraddr; /* Next free entry when writing into queue. */ /* Declaration of semaphore variables. */ int rdmutex = 1; int wrmutex = 1; int nrempty = FIFO_SIZE; int nrfull = 0; Räknande semaforer Binära semaforer

23 William Sandqvist PutFifo() GetFifo() void PutFifo( int tal ) { Fifo[wraddr] = tal; /* Write to FIFO array. */ wraddr = wraddr + 1; /* Increase FIFO array index */ /* point to free position. */ /* Wrap around if index has reached end of the array. */ if (wraddr == FIFO_SIZE ) wraddr = 0; } int GetFifo( void ) { int retval; /* Declare temporary for return value. */ retval = Fifo[rdaddr]; /* Get value from FIFO array. */ rdaddr = rdaddr + 1; /* Increase FIFO array index */ /* point to free position. */ /* Wrap around if index has reached end of the array. */ if (rdaddr == FIFO_SIZE ) rdaddr = 0; return (retval); /* Return value fetched from FIFO. */ } oslab_main.c

24 William Sandqvist Fifo - figur FIFO_SIZE = FifoEnd - Fifo

25 William Sandqvist Fifon en gemensam resurs Riskabelt med trådbyte mellan producers precis när en tråd gör PutFifo() wraddr kan bli fel! Riskabelt med trådbyte mellan consumers precis när en tråd gör GetFifo() rdaddr kan bli fel!

26 William Sandqvist Skydda Fifon med semaforer wrmutex nrempty rdmutex nrfull

27 William Sandqvist Signal() /* * Signal * Semaphore operation: add to semaphore, * possibly allowing other threads to continue. */ void Signal( int *sem ) { /* We must disable interrupts, since the operation * *sem = *sem + 1 * will require several machine instructions. * If we have a timer-interrupt and a thread-switch * the semaphore will be updated twice, * or not at all, or in some other erroneous way. */ oslab_begin_critical_region(); *sem = *sem + 1; oslab_end_critical_region(); } oslab_main.c

28 William Sandqvist Wait() /* * Wait * Sempahore operation: check semaphore, and * wait if the semaphore value is zero or less. */ void Wait( int *sem ) { /* Disable interrupts */ oslab_begin_critical_region(); while ( *sem <= 0 ) { /* If wait, enable interrupts again. */ oslab_end_critical_region(); //oslab_yield(); /* Perhaps yield here? */ /* Disable interrupts before loop. */ oslab_begin_critical_region(); } /* Semaphore is now greater than zero */ *sem = *sem - 1; /* Enable interrupts again */ oslab_end_critical_region(); } oslab_main.c

29 William Sandqvist Skydda PutFifo() med semaforer void PutFifo( int tal ) { Wait (&nrempty); /* Wait for nrempty */ Wait (&wrmutex); /* Wait for wrmutex */ Fifo[wraddr] = tal; /* Write to FIFO array */ wraddr = wraddr + 1; /* index to next free */ /* Wrap around the index if reached the end */ if (wraddr == FIFO_SIZE ) wraddr = 0; Signal (&wrmutex); /* Signal wrmutex */ Signal (&nrfull); /* Signal nrfull */ } oslab_main.c

30 William Sandqvist Skydda GetFifo() med semaforer int GetFifo( void ) { int retval; /* temporary for return value */ Wait (&nrfull); /* Wait for nrfull */ Wait (&rdmutex); /* Wait for rdmutex */ retval = Fifo[rdaddr]; /* Get value from FIFO */ rdaddr = rdaddr + 1; /* Increase FIFO index */ /* Wrap around the index if reached the end */ if (rdaddr == FIFO_SIZE ) rdaddr = 0; Signal (&rdmutex); /* Signal rdmutex */ Signal (&nrempty); /* Signal nrempty */ return retval; /* Return value from FIFO. */ } oslab_main.c

31 William Sandqvist

32 Producer() oslab_main.c void Producer( struct Prod * prodstruct ) { int next; /* to hold the prime just produced */ int prodid; /* Producer 1, 2 or 3 */ next = prodstruct -> startvalue; /* Get startvalue */ prodid = prodstruct -> id; /* Get producer number */ while( 1 ) /* Loop forever */ { next = NextPrime (next); /* Produce a new prime */ printf("Prime from P %d is %d", prodid, next); PutFifo(next); /* Write prime into FIFO. */ //oslab_yield(); /* Try to yield here? */ } }

33 William Sandqvist Consumer() oslab_main.c void Consumer( int * tal ) { int next; /* to hold the prime to consume */ int consid = *tal; /* Consumer 1 or 2 */ while( 1 ) /* Loop forever */ { next = GetFifo(); /* Get new prime from FIFO */ printf(”C %d gets prime %d", consid, next); Sleep(2000); /* Symbolic work */ //oslab_yield(); /* Try to yield here? */ } }

34 William Sandqvist main() oslab_main.c int main( void ) { int tid1, tid2, tid3, tid4, tid5; /* for Thread ID */ struct Prod prod1, prod2, prod3; /* P context */ int cons1, cons2; /* C context */ rdaddr = 0; /* FIFO initialization */ wraddr = 0; /* FIFO initialization */ printf("System starting..."); prod1.startvalue = 2000; prod1.id = 1; prod2.startvalue = 5000; prod2.id = 2; prod3.startvalue = 8000; prod3.id = 3; cons1 = 1; cons2 = 2;...

35 William Sandqvist Starta tråd … oslab_main.c tid1 = oslab_create_thread((void *)Producer,&prod1,&(stack1[0x3ff])); printf("Producer %d is created with thread-ID %d",prod1.id, tid1); /*Change this comment to start threads! tid2 = oslab_create_thread((void *)Producer,&prod2,&(stack2[0x3ff])); printf("Producer %d is created with thread-ID %d",prod2.id, tid2); tid3 = oslab_create_thread((void *)Producer,&prod3,&(stack3[0x3ff])); printf("Producer %d is created with thread-ID %d",prod3.id, tid3); tid4 = oslab_create_thread((void *)Consumer, &cons1,&(stack4[0x3ff])); printf(”Consumer %d is created with thread-ID %d",cons1, tid4); tid5 = oslab_create_thread((void *)Consumer,&cons2,&(stack5[0x3ff])); printf(”Consumer %d is created with thread-ID %d",cons2, tid5); /* End of comment. */ oslab_idle(); /* Must be called here! */ }

36 William Sandqvist Starta fler trådar … oslab_main.c tid1 = oslab_create_thread((void *)Producer,&prod1,&(stack1[0x3ff])); printf("Producer %d is created with thread-ID %d",prod1.id, tid1); /*Change this comment to start threads! */ tid2 = oslab_create_thread((void *)Producer,&prod2,&(stack2[0x3ff])); printf("Producer %d is created with thread-ID %d",prod2.id, tid2); /*tid3 = oslab_create_thread((void *)Producer,&prod3,&(stack3[0x3ff])); printf("Producer %d is created with thread-ID %d",prod3.id, tid3); tid4 = oslab_create_thread((void *)Consumer, &cons1,&(stack4[0x3ff])); printf(”Consumer %d is created with thread-ID %d",cons1, tid4); tid5 = oslab_create_thread((void *)Consumer,&cons2,&(stack5[0x3ff])); printf(”Consumer %d is created with thread-ID %d",cons2, tid5); /* End of comment. */ oslab_idle(); /* Must be called here! */ }

37 William Sandqvist Trådbytet

38 William Sandqvist Trådbytet i detalj

39 William Sandqvist Registeranvändning

40 William Sandqvist Post om 27 Ord på stacken.

41 William Sandqvist (3) Registerinnehåll sparas oslab_lowlevel_asm.s # Save registers r1 through r23, plus fp, gp, ra and ea subi sp,sp,108 # Make room for all registers. stw r1,4(sp) # R1 is saved in slot 1, not slot 0 stw r2,8(sp) stw r3,12(sp)... stw r10,40(sp) stw r11,44(sp)... stw r23,92(sp) stw r26,96(sp) stw r28,100(sp) stw r31,104(sp) stw ea,0(sp) # Special case, saved in slot 0 mov r4,sp # Copy stack pointer to R4 movia sp,oslab_system_stacktop # Use system stack Indexerad adressering används i stället för PUSH. Detta sparar 50% instruktioner!

42 William Sandqvist (4) oslab_internal_threadswitch oslab_lowlevel_c.c movia et, oslab_internal_threadswitch callr et # call C thread switch function unsigned int oslab_internal_threadswitch( unsigned int old_sp ) { unsigned int new_sp; /* Save the stack pointer of the old thread. */... /* Perform the scheduling decision (round-robin) */ oslab_running_thread += 1; if( oslab_running_thread >= oslab_current_thread_count ) oslab_running_thread = 0; /* Get the stack pointer of the new thread */... return new_sp ; }

43 William Sandqvist (5) Registerinnehåll återställs oslab_lowlevel_asm.s mov sp,r2 # Copy return value to stack pointer ldw r1,4(sp) # restore registers ldw r2,8(sp) ldw r3,12(sp) ldw r4,16(sp) ldw r5,20(sp) ldw r6,24(sp)... ldw r23,92(sp) ldw r26,96(sp) ldw r28,100(sp) ldw r31,104(sp) ldw ea,0(sp) # Special case addi sp,sp,108 eret # Return from exception Indexerad adressering används i stället för POP. Detta sparar 50% instruktioner!

44 William Sandqvist os_lab_create_thread() oslab_lowlevel_c.c int oslab_create_thread( int (*thread_function)(void *), void * thread_arg, unsigned int * thread_stack ) En ny tråd skapas med det stackinnehåll som den skulle haft om den blivit avbruten från början … unsigned int * new_thread_sp = thread_stack - 27; for( i = 1; i < 24; i += 1 ) new_thread_sp[ i ] = 0; new_thread_sp[ 24 ] = (unsigned int) oslab_internal_get_gp(); new_thread_sp[ 25 ] = 0; new_thread_sp[ 26 ] = (unsigned int) oslab_exit_thread; new_thread_sp[ 0 ] = (unsigned int) thread_function; new_thread_sp[ 4 ] = (unsigned int) thread_arg; Post med 27 ord på stacken.

45 William Sandqvist Ex. Fördelning av CPU-tid FIFO har 10 platser Wait utan Yield Kapacitet: P 4 st, C 8 st


Download ppt "William Sandqvist Övning 9 Trådar och Semaforer."

Similar presentations


Ads by Google