Demonstration of a spin lock

Dependencies:   ELEC350-Practicals-FZ429

Fork of Task617Solution-mbedos-FZ429 by University of Plymouth - Stages 1, 2 and 3

Files at this revision

API Documentation at this revision

Comitter:
noutram
Date:
Thu Nov 09 14:43:39 2017 +0000
Parent:
7:bd75e7717b58
Commit message:
Demonstration of a spin lock

Changed in this revision

ELEC350-Practicals-FZ429.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
myasm.s Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ELEC350-Practicals-FZ429.lib	Thu Nov 09 14:43:39 2017 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/University-of-Plymouth-Stage-2-and-3/code/ELEC350-Practicals-FZ429/#6f9f2e93a0be
--- a/main.cpp	Tue Oct 31 15:40:25 2017 +0000
+++ b/main.cpp	Thu Nov 09 14:43:39 2017 +0000
@@ -1,84 +1,117 @@
 #include "mbed.h"
-#include "rtos.h"
 #include "string.h"
 #include <stdio.h>
 #include <ctype.h>
+#include "sample_hardware.hpp"
 
-#define DELAY 200
+
+#define RED_DONE 1
+#define YELLOW_DONE 2
+
 
-DigitalOut onBoardLED(LED1);
-DigitalOut redLED(PE_15);
-DigitalOut yellowLED(PB_10);
-DigitalOut greenLED(PB_11);
+//Function declarations
+void countUP();
+void countDOWN();
+extern "C" void spinlock(volatile int *arg);
+extern "C" void spinunlock(volatile int *arg);
 
-DigitalIn  onBoardSwitch(USER_BUTTON);
-DigitalIn  SW1(PE_12);
-DigitalIn  SW2(PE_14);
+//MUTEX Lock
+Mutex countLock;
+volatile int _spinLock = 1;
 
 //Thread ID for the Main function (CMSIS API)
 osThreadId tidMain;
 
-//Thread sychronisation primatives
-Mutex lock1;
-Mutex lock2;
-unsigned long sw1Count = 0;
-unsigned long sw2Count = 0;
+//Stared mutable state
+volatile int count = 0;
 
-void thread1() 
+// *************************************************************
+// * TRY THIS WITH AND WITHOUT UNCOMMENTING THE FOLLOWING LINE *
+// * Note the speed difference for this particular case.
+// *************************************************************
+
+//#define SPIN
+
+void inline increment()
 {
-    printf("Entering thread 1\n");
-    while (true) {
-        yellowLED = 1;
-        
-        //Start critical section
-        lock1.lock();
- 
-        sw1Count++;
-        printf("\nCount1 = %lu", sw1Count);
-        
-        Thread::wait(1); //1ms
-        
-        //End critical section
-        lock1.unlock();
-                
-        if (SW1 == 1) {
-            lock2.lock();
-            sw2Count--;
-            lock2.unlock();   
-        }
-        
-        yellowLED = 0;
-        Thread::wait(DELAY);       
-    }
+  //**** Take lock ****
+    #ifdef SPIN
+    spinlock(&_spinLock); 
+    #else
+    countLock.lock();
+    #endif
+    
+    count++;
+    
+    //**** Release lock ****
+    #ifdef SPIN
+  spinunlock(&_spinLock);   
+    #else
+    countLock.unlock();
+    #endif
 }
 
-void thread2() 
+
+
+void inline decrement()
+{
+  //**** Take lock ****
+    #ifdef SPIN
+    spinlock(&_spinLock); 
+    #else
+    countLock.lock();
+    #endif
+    
+    count--;
+    
+    //**** Release lock ****
+    #ifdef SPIN
+    spinunlock(&_spinLock);   
+    #else
+    countLock.unlock();
+    #endif
+}
+//Threads
+void countUP()
 {
-    printf("Entering thread 2\n");  
-    while (true) {
-        redLED = 1;
-        
-        //Start critical section
-        lock2.lock();
-        
-        sw2Count++;
-        printf("\nCount2 = %lu", sw2Count);
-        
-        Thread::wait(1);  //1ms
+    redLED = 1;
+    
+    for (unsigned int n=0; n<100000; n++) {      
+                increment();
+                increment();
+                increment();
+                increment();
+                increment();
+                increment();
+                increment();
+                increment();
+                increment();
+                increment();            
+    }
+    
+    redLED = 0;
+    osSignalSet(tidMain, RED_DONE);  //Signal main thread we are done
+}
+
+void countDOWN()
+{
+    yellowLED = 1;
+    
+    for (unsigned int n=0; n<100000; n++) {      
+                decrement();
+                decrement();
+                decrement();
+                decrement();
+                decrement();
+                decrement();
+                decrement();
+                decrement();
+                decrement();
+                decrement();
+    }   
         
-        //End critical section
-        lock2.unlock();
-        
-        if (SW2 == 1) { 
-            lock1.lock();
-            sw1Count--;
-            lock1.unlock();  
-        }  
-
-        redLED = 0;
-        Thread::wait(DELAY); 
-        
-    } 
+    yellowLED = 0;    
+    osSignalSet(tidMain, YELLOW_DONE); //Signal main thread we are done
 }
 
 
@@ -86,22 +119,36 @@
 int main() {
     redLED    = 0;
     yellowLED = 0;
-    greenLED  = 0;
-                
-    //Main thread ID
-    tidMain = Thread::gettid();  
+    greenLED  = 1;
     
     //Threads
-    Thread t1, t2;
+    Thread t1;
+    Thread t2;
+    tidMain = Thread::gettid();  
     
-    t1.start(thread1);
-    t2.start(thread2);
-    
-    printf("Main Thread\n");
-    while (true) {
-        Thread::wait(osWaitForever);
+    //Press the switch to run concurrently
+    if (onBoardSwitch == 1) {
+        printf("Running sequntially\n");
+        countUP();
+        countDOWN();        
+    } else {
+        printf("Running concurrently\n");
+        t1.start(countUP);           
+        t2.start(countDOWN);    
+  
+        //Wait for the ALL_ON signal
+        Thread::signal_wait(RED_DONE,osWaitForever);
+        Thread::signal_wait(YELLOW_DONE,osWaitForever);        
     }
 
+    printf("Final result = %d\n", count);
+    if (count == 0) {
+        greenLED = 0;
+    }
+        
+    while(true);
 }
 
+
+
    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myasm.s	Thu Nov 09 14:43:39 2017 +0000
@@ -0,0 +1,29 @@
+    AREA asm_func, CODE, READONLY
+; Export my_asm function location so that C compiler can find it and link
+    EXPORT myasm
+myasm
+    
+    ; Write assmebler here
+    MOV R1, #0x20000000
+    BX      R1              ; THIS IS BAD
+    BX      LR
+    
+    EXPORT spinlock
+spinlock
+    LDREX   R1,[R0]     ;Read counter
+    SUBS    R1, #1      ;Subtract 1
+    ITT     PL          ;IF True True >= 0
+    STREXPL R2,R1,[R0]      ;TRY UPDATE
+    CMPPL   R2,#0           ;SUCCEED?
+    BNE     spinlock
+    BX      LR
+
+    EXPORT spinunlock
+spinunlock
+    LDREX   R1,[R0]
+    ADD     R1,#1
+    STREX   R2,R1,[R0]
+    CMP     R2,#0
+    BNE     spinunlock
+    BX      LR
+    END
\ No newline at end of file