Lect 06-Communication
Lect 06-Communication
memory
CPU 1 CPU 2
Race condition in shared memory
Assume a “flag” used to synchronize access to shared
memory
Flag = 1 when shared item is being used
Flag = 0 when shared item is not being used
To access the item: CPU must see flag = 0 and write flag = 1
Problem when two CPUs try to write the same location:
CPU 1 reads flag and sees 0.
CPU 2 reads flag and sees 0. Flag
ADR r0,SEMAPHORE
LDR r1,#1
GETFLAG SWP r1,r1,[r0]
BNZ GETFLAG
Critical regions
Critical region: section of code that cannot be interrupted
by another process.
Examples:
writing shared memory;
accessing I/O device.
Mutual Exclusion Example
System variables: Lock = 0;
while (1){ while (1){
Lock = 0; Lock = 0;
Remainder Remainder
Process 1 Process 2
Task and Device Queues
Processes queued for shared device access
Semaphores
Semaphore: OS primitive for controlling access to
critical regions.
Sempaphore can be “binary” or “counting”
Protocol:
1. Get access to semaphore with P() function.
(Dutch “Proberen” – to test)
2. Perform critical region operations.
3. Release semaphore with V() function.
(Dutch “Verhogen” – to increment)
Task synchronization
Task1 Task2
signal(&S1) signal(&S2)
wait (&S2) wait(&S1)
tasks synchronize at this point
Potential deadlock
Tasks 1 and 2 each require two resources, R1 and R2,
with access controlled by S1 and S2, respectively
Task1 Task2
wait(&S1) wait(&S2)
//have R1 //have R2
wait (&S2) wait(&S1)
//wait for R2 //wait for R1
DEADLOCK!!
Mutual Exclusion (MUTEX)
Binary semaphore
Provide exclusive access to a resource
osMutexId_t m_id; //MUTEX ID
m_id = osMutexNew(attr); //create MUTEX obj
attr = osMutexAttr_t structure or NULL for default
status = osMutexAcquire(m_id, timeout);
Wait until MUTEX available or until time = “timeout” Timeout arguments
timeout = 0 to return immediately for other objects
timeout = osWaitForever for infinite wait have same options
“status” = osOK if MUTEX acquired
osErrorTimeout if not acquired within timeout
osErrorResource if not acquired when timeout=0 specified
status = osMutexRelease(m_id); //release the MUTEX
status = osOK if released, osErrorResource if invalid operation (not owner)
osMutexAcquire(mutex_id, timeout)
osMutexRelease(mutex_id)
Limit access to
shared resource to
one thread at a time.
Special version of a
“semaphore”
CMSIS-RTOS2 Semaphores
Counting semaphore
Allow up to t threads to access a resource
osSemaphoreId s_id; //semaphore ID
s_id = osSemaphoreNew(max_tokens, init_tokens, attr);
Create s1; set max and initial #tokens
attr osSemaphoreAttr_t structure or NULL for defaults
status = osSemaphoreAcquire(s_id, timeout);
Wait until token available or timeout
status = osOK if token obtained (#tokens decremented)
osErrorTimeout if token not obtained before timeout
osErrorResouce if token not obtained and timeout=0
status = osSemaphoreRelease(s_id);
Release token
status = osOK if token released (#tokens incremented)
osErrorResouce if max token count reached
osErrorParameter if s_id invalid
Permit fixed number of
threads/ISRs to access a
pool of shared resources.
osSemaphoreAcquire(sem_id,timeout)
osSemaphoreRelease(sem_id)
osSemaphoreGetCount(sem_id)
CMSIS-RTOS semaphore example
osSemaphoreId_t sid_Thread_Semaphore; // semaphore id
int i, oflags;
sem_t *my_semaphore; //descriptor for sem.
i = sem_wait(my_semaphore); // P()
// wait for semaphore, block if not free
// now do useful work
i = sem_post(my_semaphore); // V()
CPU 1 CPU 2
message message
message
Message passing via mailboxes
Mailbox = message buffer between two processes (FIFO)
full Process B
(receiving)
full
Process A filling
(sending)
empty
// message queue id
osMessageQueueId_t mid_MsgQ;
void Thread2 (void *argument) { //This thread receives data from Thread1
MSGQUEUE_OBJ_t msg;
osStatus_t status;
while (1) {
; // Insert thread code here...
status = osMessageQueueGet (mid_MsgQ, &msg, NULL, NULL); // wait for message
if (status == osOK) {
; // process data in msg.Buf[msg.Idx]
} }}
CMSIS-RTOS mail queues (eliminated in RTOS2)
OSMboxCreate(msg)
create mail box & insert initial msg
OSMboxPost(box, msg)
add msg to box
OSMboxAccept(box)
get msg if there, o/w continue
OSMboxPend(box,timeout)
get msg if there, o/w wait up to timeout
OSMboxQuery(box,&data)
return information about the mailbox
Example: Mentor Graphics
“Nucleus” POSIX Kernel
Nucleus POSIX demo program
(Mentor Graphics EDGE tools for SoC/ARM)
Six tasks/five “functions”
a system timer
a task that queues messages
a task that retrieves queued messages
two instances of a task that uses a resource for 100 “ticks”
a task that waits for event signals
/* Create task 0 */
//allocates memory for task stack from memory pool
NU_Allocate_Memory(&System_Memory, &pointer,
TASK_STACK_SIZE, NU_NO_SUSPEND);
void task_1( )
{
Send_Message = 0;
while (1) {
/* queue a message */
/* suspend if queue full or time slice */
status = ND_Send_To_Queue(&Queue_0,
&Send_Message, 1, NU_SUSPEND);
Send_Message++;
}
}
Demo program: Queue-receiving task
void task_2( )
{
message_expected = 0;
while (1) {
/* retrieve a message */
/* suspend if queue empty or time slice */
status = ND_Receive_From_Queue(&Queue_0,
&Receive_Message, 1, &received_size,
NU_SUSPEND);
message_expected++;
}
}
Demo program: Use resource task
(two instances in the demo)