Beruflich Dokumente
Kultur Dokumente
VxWorks
VxWorks
VxWorks is a commercial hard real time operating system
developed by wind river systems.
The main idea: use monolithic kernel to schedule user
tasks according to user defined priorities. Maximize kernel
timing predictability.
Gives the users maximal control.
VxWorks
A dedicated real time system, not intended as a general
purpose OS.
lacks many modern os features that interfere with real time
performance (flat memory model, no paging).
VxWorks
Scheduling is done using a preemptive priority driven
approach, priorities are chosen arbitrarily by the user (0-255).
Priorities can be changed by the user at runtime but this is
discouraged.
A user can lock a task so that it can‟t be preempted even by
higher priority tasks or interrupts.
This allows the use of the fixed priority response time analysis
to check schedulability offline.
VxWorks
Is resource sharingaware and has a priority inheritance
built in.
Optimizations in implementation of the context switch
and the return from interrupts.
The kernel never disables NMI (non-maskable interrupts)
so they are always available to the user.
VxWorks - limitations
Lacks many modern OS features.
Guaranteeing the deadlines is the responsibility of the user
at design time.
Doesn‟t support most modern applications and APIs (only
a small subset of POSIX).
Despite the flat memory model dynamic memory
allocation still cases memory fragmenting, which increases
timing unpredictability.
Tornado: An Embedded System Development Tool
Tornado
An IDE to develop real-time and embedded
applications with minimal intrusion on the target
system.
Tornado comprises:
VxWorks, a high-performance real-time operating system.
Application-building tools (compilers and associated
programs).
IDE for
managing projects,
host-target communication,
running, debugging, and monitoring VxWorks applications.
The Tornado IDE
An integrated source-code editor.
A project management facility.
Integrated C and C++ compiler and linker.
The browser, a visual monitoring tool for target system.
CrossWind, a source-level debugger.
WindSh, C and Tcl command shell that controls the target.
VxWorks target simulator VxSim.
WindView software logic analyzer for the target simulator.
Overview of Tornado IDE
exit (code)
Equivalent to a taskDelete( ) of self.
code parameter is stored in the TCB field exitCode.
TCB may be examined for post-mortem debugging
Task Restart
taskResume (tid)
Removes suspension.
Note:
Usually taskSuspend() and taskResume() are used for debugging
and development purposes.
Task Delay
taskDelay (ticks)
To delay a task for a specified number of system clock ticks:
Dealing with Tornado
Creating the Task
# include <vxWorks.h>
#include < stdio.h>
int main ()
{
printf (“Welcome To Tornado World from main()…\n”);
return 0;
}
#include <stdio.h>
#include<VxWorks.h>
int fun();
int main()
{
printf(“\n This is my First VxWorks Program……\n”);
fun();
printf(“I am in MAIN after Function Calling…\n”);
return 0;
}
int fun()
{
Printf(“\n I am in Function Now…….\n”);
}
Example for taskSpawn()
# include <vxWorks.h>
#include < stdio.h>
void fun();
int tid1;
int main ()
{
printf(“\n This is my First VxWorks Program……\n”);
tid1=taskSpawn("task1",110,0,2000,fun,0,0,0,0,0,0,0,0,0,0);
printf(“I am in MAIN after Task Spawn…\n”);
return 0;
}
void fun();
{
printf (“Welcome To Tornado from Task – fun1\n”);
}
Example for taskSpawn()
#include"VxWorks.h"
#include"stdio.h"
#include"taskLib.h"
void fun1(int,int);
void fun2(int,int);
int tid1,tid2;
void f(void)
{
tid1=taskSpawn("task1",100,0,2000,fun1,10,200,0,0,0,0,0,0,0,0);
tid2=taskSpawn("task2",90,0,2000,fun2,20,100,0,0,0,0,0,0,0,0);
}
#include <stdio.h> {
# define COUNT 10 }
Void rootApp()
{
int i, taskid;
Printf(“I am in myApp…\n”);
for (i=0;i<COUNT;i++)
taskid=taskSpawn(“tmyApp1”,90,0x100,2000,(FUNCPTR)myApp1,0,0,0,0,0,0,0,0,0);
return 0;
}
Program to validate state of task
int rootApp()
#include <stdio.h> {
#include <vxWorks.h> printf (“I am in rootApp..\n”);
#include <taskLib.h> tid1=taskSpawn(“tmyApp1”,101,0,2000,
(FUNCPTR)myApp1,1,0,0,0,0,0,0,0,0,0);
#include <string.h>
tid1=taskSpawn(“tmyApp2”,102,0,2000,
(FUNCPTR)myApp2,1,0,0,0,0,0,0,0,0,0);
int myApp1(); return 0;
int myApp2(); }
int tid1, tid2; int myApp1(int k, int j)
int id1,id2; {
printf(“I am in myApp1..\n”);
taskSuspend(0);
STATUS ret;
If((ret=taskStatusString(tid1, status))==-1)
Char * status;
printf(“\n Retruns ERROR…\n”);
printf(“status of task = %s\n”,status);
printf(“\n I am in myApp1 after suspension\n”);
return 0;
}
Program to validate state of task
int myApp2(int k, int j)
{
printf (“I am in myApp2..\n”);
status =malloc (20);
If((ret=taskStatusString(tid1, status))==-1)
printf(“\n myApp1 Retruns ERROR…\n”);
printf(“status of task myApp1 = %s\n”,status);
takResume(tid1);
return 0;
}
Program for taskSafe / taskUnsafe():
int rootApp()
{
#include <stdio.h>
printf (“I am in rootApp..\n”);
#include <vxWorks.h>
s = (char *) malloc (10);
#include <taskLib.h> tid1=taskSpawn(“tmyApp1”,101,0,2000,
(FUNCPTR)myApp1,1,0,0,0,0,0,0,0,0,0);
#include <string.h>
tid1=taskSpawn(“tmyApp2”,102,0,2000,
(FUNCPTR)myApp2,1,0,0,0,0,0,0,0,0,0);
int myApp1(int, int ); return 0;
}
int myApp2(int, int );
int myApp1(int k, int j)
int tid1, tid2;
{
int id1,id2; char *st = (char *) malloc (20);
taskSafe();
taskDelay(10);
Char * s;
printf(“\n I am in myApp1 \n”);
taskStatusString(tid1, st)
printf(“status of task = %s\n”,st);
taskUnsafe();
printf(“AFTER UNSAFE…\n”);
return 0;
}
Program for taskSafe /
taskUnsafe():
int myApp2(int k, int j)
{
printf (“I am in myApp2..\n”);
taskDelete(tid1);
printf(“I am in myApp2 after DELETION..\n”);
return 0;
}
taskbrowser void fun1(int i,int j)
{
#include"VxWorks.h" while(1)
#include"stdio.h" {
#include"taskLib.h" printf("this is function1 %d,%d\n",i,j);
taskDelay(100);
void fun1(int,int);
printf("value of y is %d \n",y);
void fun2(int,int);
}
int tid1,tid2,y=10;
}
void f(void)
void fun2(int a,int b)
{ {
tid1=taskSpawn("task1",90,0x100,2000,(FUNCP while(1)
TR)fun1,10,20,0,0,0,0,0,0,0,0); {
tid2=taskSpawn("task2",100,0x100,2000,(FUNC
printf("this is function2 %d,%d\n",a,b);
PTR)fun2,20,60,0,0,0,0,0,0,0,0);
taskDelay(100);
} printf("value of y is %d \n",y);
}
}
taskidverify
#include"VxWorks.h" void fun1(int i,int j)
#include"stdio.h" {
#include"taskLib.h" int k;
void fun1(int,int); printf("this is function1 %d%d\n",i,j);
void fun2(int,int); k=taskIdSelf();
int tid1,tid2,p; printf("task1 id is %d\n",k);
void f(void) p=taskIdVerify(tid1);
{ printf("task id is verified in task1
tid1=taskSpawn("task1",100,0x100,2000,f %d\n",p);
un1,10,200,0,0,0,0,0,0,0,0); }
tid2=taskSpawn("task2",90,0x100,2000,fu
n2,20,100,0,0,0,0,0,0,0,0); void fun2(int a,int b)
p=taskIdVerify(tid1); {
printf("task id is verified in f %d",p); printf("this is function2 %d,%d\n",a,b);
} }
Inter task Synchronization
SEMAPHORES
Binary Semaphores
SEM_ID semBCreate (options, initialState)
options Specify queue type (SEM_Q_PRIORITY or
SEM_Q_FIFO) for tasks pended on this
semaphore.
initialState Initialize semaphore to be available
(SEM_FULL) or unavailable (SEM_EMPTY).
Semaphores used for synchronization are typically
initialized to SEM_EMPTY (event has not occurred).
Returns a SEM_ID, or NULL on error.
Symbolic constants defined in semLib.h.
Taking a Semaphore
STATUS semTake (semId, timeout)
semId The SEM_ID returned from semBCreate( ).
timeout Maximum time to wait for semaphore.
Value can be clock ticks, WAIT_FOREVER, or NO_WAIT.
Can pend the task until either
- Semaphore is given or
- Timeout expires.
- Semaphore left unavailable.
Returns OK if successful, ERROR on timeout (or invalid semId).
Giving a Semaphore
STATUS semGive (semId)
Unblocks a task waiting for semId.
If no task is waiting, makes semId available.
Returns OK, or ERROR if semId is invalid.
Synchronizing Multiple Tasks
STATUS semFlush (semId)
Unblocks all tasks waiting for semaphore.
Does not affect the state of a semaphore.
Useful for synchronizing actions of multiple tasks.
Example void c(void)
{
#include"VxWorks.h"
semTake(semBinary,WAIT_FOREVER);
#include"taskLib.h"
printf("\n task 1 has taken sem\n");
#include"semLib.h"
printf(“UNIVERSITY\n");
#include"stdio.h"
semGive(semBinary);
void c(void);
printf(" task 1 released sem\n");
void b(void);
}
SEM_ID semBinary;
void b(void)
void f()
{
{
semTake(semBinary,WAIT_FOREVER);
semBinary=semBCreate(SEM_Q_FIFO,SE
M_FULL); printf(" \ntask 2 has taken sem\n");
taskSpawn("task1",90,0,2000,(FUNCPTR)c, printf(“VIT\n");
0,0,0,0,0,0,0,0,0,0); taskDly(2000);
taskSpawn("task2",80,0,2000,(FUNCPTR)b, semGive(semBinary);
0,0,0,0,0,0,0,0,0,0); printf(" task2 released sem\n");
} }
Example void c(void)
{
#include"VxWorks.h" Int i;
#include"taskLib.h" for (i=0;i<COUNT;i++)
#include"semLib.h" {
#include"stdio.h“ semTake(semid1,WAIT_FOREVER);
# define COUNT 10 printf("\n I am in C and
global=%d….\n“,++global);
void c(void); semGive(semid1);
void b(void); }
SEM_ID semid1; }
int global=0; void b(void)
{
void f() Int i;
{ for (i=0;i<COUNT;I++)
int tid1, tid2; {
printf(“I am in Main…\n”); semTake(semid1,WAIT_FOREVER);
semid1=semBCreate(SEM_Q_FIFO,SEM_FULL); printf("\n I am in C and
global=%d….\n“,--global);
tid1=taskSpawn("task1",90,0,2000,(FUNCPTR)c,0,0,0,0,
0,0,0,0,0,0); semGive(semid1);
tid2=taskSpawn("task2",80,0,2000,(FUNCPTR)b,0,0,0,0, }
0,0,0,0,0,0);
}
}
Example int rootApp()
{
#include <taskLib.h> printf("*****************************\n");
#include<semLib.h> printf("I am in rootApp....\n");
semid1=semBCreate(SEM_Q_PRIORITY,SEM_EMPTY);
int tid1, tid2,tid3,tid4; semid2=semBCreate(SEM_Q_PRIORITY,SEM_EMPTY);
SEM_ID semid1,semid2,semid3; semid3=semBCreate(SEM_Q_PRIORITY,SEM_EMPTY);
tid1=taskSpawn("tmyApp1",101,0,2000,(FUNCPTR)myApp
int myApp1(); 1,0,0,0,0,0,0,0,0,0,0);
int myApp2(); tid2=taskSpawn("tmyApp2",101,0,2000,(FUNCPTR)myApp
int myApp3(); 2,0,0,0,0,0,0,0,0,0,0);
int myApp4(); tid3=taskSpawn("tmyApp3",101,0,2000,(FUNCPTR)myApp
3,0,0,0,0,0,0,0,0,0,0);
tid4=taskSpawn("tmyApp4",101,0,2000,(FUNCPTR)myApp
4,0,0,0,0,0,0,0,0,0,0);
return 0;
}
Example
int myApp3()
int myApp1()
{
{
semTake(semid3,WAIT_FOREVER);
semTake(semid1,WAIT_FOREVER);
printf(“3\t");
printf(“1\t");
semGive(semid2);
return 0;
return 0;
}
}
int myApp2()
int myApp4()
{
{
semTake(semid2,WAIT_FOREVER);
printf(“2\t");
printf(“4\t");
semGive(semid1);
semGive(semid3);
return 0;
return 0;
}
}
Example
Re-modify the above code to get the following output:
(i) 3421
(ii) 1234
(iii) 4123
Example
Create a Single Binary semaphore for printing
Create 5 tasks
4 tasks try to get and release the semaphore for PRINT
semBCreate(SEM_Q_PRIORITY, SEM_EMPTY)
semTake(semid1, WAIT_FOREVER)
semGive(semid1)
5th task for semaphore flush
semFlush(semid1)
Examine the output in the tornado IDE.
Count semaphore
SEM_ID semCCreate (options, initialState)
options : Specify queue type (SEM_Q_PRIORITY
or SEM_Q_FIFO) for tasks pended on
this semaphore.
initialState : Initial count
Returns a SEM_ID, or NULL on error.
When a task takes a counting semaphore, using semTake( ), subsequent
action depends on the state of the count:
◦ if the count is non-zero, it is decremented and the calling task continues
executing.
◦ If the count is zero, the task will be blocked, pending the availability of
the semaphore.
◦ If a timeout is specified and the timeout expires, the pended task will be
removed from the queue of pended tasks and enter the ready state with an
ERROR status.
◦ A pended task is ineligible for CPU allocation. Any number of tasks may
be pended simultaneously on the same counting semaphore.
When a task gives a semaphore, using semGive( ), the next available task in
the pend queue is unblocked
SemCCreate
#include"vxWorks.h" int rootApp()
#include"stdio.h" {
#include"semaphore.h" printf("\n*********************************\n");
#include"taskLib.h" printf("I am in rootApp Now......\n");
semid1=semCCreate(SEM_Q_PRIORITY,1);
int myApp1(); tid1=taskSpawn("tmyApp1",200,0,2000,(FUNCPTR)myA
int myApp2(); pp1,0,0,0,0,0,0,0,0,0,0);
int myApp3(); tid2=taskSpawn("tmyApp2",150,0,2000,(FUNCPTR)myA
pp2,0,0,0,0,0,0,0,0,0,0);
int myApp4();
tid3=taskSpawn("tmyApp3",100,0,2000,(FUNCPTR)myA
int myApp5(); pp3,0,0,0,0,0,0,0,0,0,0);
tid4=taskSpawn("tmyApp4",50,0,2000,(FUNCPTR)myAp
SEM_ID semid1; p4,0,0,0,0,0,0,0,0,0,0);
int tid1, tid2,tid3,tid4,tid5; tid5=taskSpawn("tmyApp5",60,0,2000,(FUNCPTR)myAp
p5,0,0,0,0,0,0,0,0,0,0);
return 0;
}
int myApp3()
{
SemCCreate semTake(semid1,WAIT_FOREVER);
printf("I am in myApp3.....\n");
semGive(semid1);
int myApp1() return 0;
{ }
int myApp4()
semTake(semid1,WAIT_FOREVER); {
printf("I am in myApp1.....\n"); semTake(semid1,WAIT_FOREVER);
SEM_ID semid1;
int tid1, tid2,tid3,tid4;
int myApp2()
SemMCreate {
semTake(semid1,WAIT_FOREVER);
printf("I am in myApp2.....\n");
#include"semaphore.h" tid1=taskSpawn("tmyApp1",50,0,2000,(FUNCPTR)myA
pp1,0,0,0,0,0,0,0,0,0,0);
#include"taskLib.h"
tid2=taskSpawn("tmyApp2",50,0,2000,(FUNCPTR)myA
pp2,0,0,0,0,0,0,0,0,0,0);
int myApp1();
int myApp2(); return 0;
}
SEM_ID semid1;
int tid1, tid2;
Ownership Property of Mutex
Semaphore
int myApp2()
int myApp1()
{
{
int k;
k=semGive(semid1);
int k; printf("The Return value = %d\n",k);
k=semTake(semid1,WAIT_FOREVE
R);
return 0;
printf("I am in myApp1.....\n"); }
printf("The Return Value of SemTake
= %d\n",k);
taskDelay(10);
printf("I am in myApp1 - After
Delay.....\n");
return 0;
}
/* Recursive function of Mutex
Semaphore */
/* Recursive function of Mutex int rootApp()
Semaphore */ {
printf("\n*********************************\n");
#include"vxWorks.h" printf("I am in rootApp Now......\n");
#include"stdio.h" semid1=semMCreate(SEM_Q_PRIORITY);
#include"semaphore.h" tid1=taskSpawn("tmyApp1",50,0,2000,(FUNCPTR)myA
pp1,0,0,0,0,0,0,0,0,0,0);
#include"taskLib.h"
SEM_ID semid1;
int tid1;
/* Recursive function of Mutex
Semaphore */
int recFun()
int myApp1()
{
{
semTake(semid1,WAIT_FOREVER);
printf("I am in recFun...\n");
semTake(semid1,WAIT_FOREVER); semGive(semid1);
printf("I am in myApp1.....\n"); return 0;
recFun(); }
semTake(semId,WAIT_FOREVER);
printf("\nTASK A\n");
taskId3=taskSpawn("TASK3",20,0x100,2400,(FUNC
PTR)c,0,0,0,0,0,0,0,0,0,0);
printf("TASK A after function\n");
semGive(semId);
}
SemMcreate
void b(void)
{
semTake(semId,WAIT_FOREVER);
printf("\nTASK B\n");
semGive(semId);
}
void c(void)
{
semTake(semId,WAIT_FOREVER);
printf("\nTASK C\n");
semGive(semId);
}
SemMcreate
#include"stdio.h" void a(void)
#include"VxWorks.h" {
semTake(semId,WAIT_FOREVER);
#include"taskLib.h" printf("\nTASK A\n");
void a(void); b();
void b(void); printf("TASK A after function\n");
semGive(semId);
int taskId1,taskId2;
}
SEM_ID semId;
void b(void)
{
void k()
semTake(semId,WAIT_FOREVER);
{ printf("\nTASK B\n");
semId=semBCreate(SEM_Q_FIFO,1); semGive(semId);
}
taskId1=taskSpawn("TASK1",50,0x100,2400,(FU
NCPTR)a,0,0,0,0,0,0,0,0,0,0);
taskId2=taskSpawn("TASK2",60,0x100,2400,(FU
NCPTR)b,0,0,0,0,0,0,0,0,0,0);
}
Intertask Communication
Inter task communication
Two mechanisms are provided by RTOS for task communication:
Message queues /Shared Memory
Signals/ Events
In addition, we will discuss the following mechanisms that can be
used in specific situation (not recommended)
Function calls
Accessing of variables
Message queues/shared memory are used to pass the data, while
signals/events are used to signal other tasks.
86
Message queues
Message queues are FIFO structure.
Acts as a buffer between two tasks.
A task need not consume the data passed by another immediately.
1
2
3
87
Message queues …..
To use a message queue, the first step is to create one.
Creation of a queue returns a queue ID.
If any task wants to post some message to a task, it should use its
queue ID.
qid = queue_create (“MyQueue”, QUEUE_OPTION)
Each queue can be usually configured as fixed size/ variable size.
Most of RTOS will provide at least fixed size entries.
88
FIFO / Priority Queues
Normally queues are FIFO.
But priority options can also be used if multiple tasks are blocking
on a single queue and a message is posted in the queue.
The queue can be configured to deliver a task that blocked the
queue first or the task that has higher priority.
3 3
10 4
10
89
Using queues
T1 T2
Q1 Q2
T3
Q3
90
Using queues ….
It is a good practice to associate a queue with a task.
The queue can be addressed through its unique mail id.
Whenever a message needs to be posted to a task, it should
be posted to the corresponding queue.
When we create multiple queues for the same task, we might
end up blocking inappropriately.
For ex. Consider a case where there are 2 queues Q1 and Q2
associated with a task TA.
// Task A Code
queue_recieve (qid_1, pmessage1);
queue_recieve (qid_2, pmessage2);
void b(void)
{
char msgBuf3[6]={0};
char msgBuf4[10]={0};
msgQReceive(mesgQueueId1,msgBuf3,6,WAIT_FOREVER);
msgQReceive(mesgQueueId1,msgBuf4,10,WAIT_FOREVER);
printf("\nfirst messages from msg queue is %s\n",msgBuf3);
printf("\nsecond Message received received from message queue %s\n",msgBuf4);
}
example
#include"VxWorks.h"
#include"msgQLib.h"
#include"stdio.h"
#include"taskLib.h"
void a(void);
void b(void);
MSG_Q_ID mesgQueueId1;
char msgBuf1[8];
void f()
{
mesgQueueId1=msgQCreate(4,50,0x00);
taskSpawn("task1",70,0x100,2000,(FUNCPTR)a,0,0,0,0,0,0,0,0,0,0);
taskSpawn("task2",80,0x100,2000,(FUNCPTR)b,0,0,0,0,0,0,0,0,0,0);
}
example
void a(void)
{
char msgBuf1[8]=“Embedded";
char msgBuf2[8]=“Systems";
msgQSend(mesgQueueId1,msgBuf1,50,WAIT_FOREVER,MSG_PRI_NORMAL);
msgQSend(mesgQueueId1,msgBuf2,50,WAIT_FOREVER,MSG_PRI_URGENT);
printf("\nMessages are send to tasks from task1\n");
}
void b(void)
{
msgQReceive(mesgQueueId1,msgBuf1,50,WAIT_FOREVER);
printf("\n%s\n",msgBuf1);
msgQReceive(mesgQueueId1,msgBuf1,50,WAIT_FOREVER);
printf("\n%s\n",msgBuf1);
printf("\nMessage is received in task2\n");
}
SHARED MEMORY
Shared Memory
Two or more tasks can exchange information by reading and writing
the same area in memory.
Data exchange takes place with zero copying because buffer is
just one deep.
For the rest any policy can be implemented on the top of shared
memory.
DMA area is very popular for the usage of shared memory.
Limit availability of RAM memory.
Shared memory must be reserved from OS and locked into RAM.
Handshaking protocol is used among the tasks to know the
freshness of data in shared memory.
Common approach use counter to indicates how many writes
have already take place.
Shared Memory
Shared memory has the properties of a so called block device.
Programs can access that arbitrary blocks on the device in any
sequence.
Character devices can access the data in a specified linear sequence
FIFO.
Its mediator policy:
◦ Loss free
◦ Non blocking
◦ Many to many /One to one
◦ Buffered.
Some FIFO support blocking for synchronization at the reader‟s end so
readers can woken up as soon as new data has arrived. have task
queue in which blocked tasks can wait.
In VxWorks
Inter task communication
It permits independent tasks to coordinate their actions.
VxWorks provide rich set of inter task communication mechanisms:
◦ Shared memory for simple sharing of data.
◦ Semaphores for basic mutual exclusions and synchronization.
◦ Msg Queue/pipe for inter task message passing within a CPU.
◦ Sockets / RPC for network-transparent inter task
communication.
◦ Signals for exception handling
VxMP provides intertask communications over the back plane for
task running on different CPUs.
This includes shared semaphore, shared message queues, shared
memory, shared name database.
memPartCreate( )
PART_ID memPartCreate(char * pPool, unsigned poolSize ) -
create a memory partition
pPool is the global address of shared memory dedicated to the partition
poolSize is the size in bytes of shared memory dedicated to the partition
DESCRIPTION
This routine creates a new memory partition containing a specified memory
pool.
It returns a partition ID, which can then be passed to other routines to
manage the partition (i.e., to allocate and free memory blocks in the partition).
RETURNS
The partition ID, or NULL if there is insufficient memory
memPartAlloc( )
memPartAlloc(PART_ID partId,unsigned nBytes ) -
allocate a block of memory from a partition
partId: memory partition to allocate from
nBytes: number of bytes to allocate
DESCRIPTION
This routine allocates a block of memory from a specified
partition.
The size of the block will be equal to or greater than nBytes.
RETURNS
pointer, or ERROR if the block is invalid.
memPartFree( )
memPartFree(PART_ID partId, char * pBlock ) - free a block of
memory in a partition
partId: memory partition to add block to
pBlock : pointer to block of memory to free
DESCRIPTION
This routine returns to a partition's free memory list a block of memory previously
allocated with memPartAlloc( ).
RETURNS
OK, or ERROR if the block is invalid.
memPartAddToPool( )
memPartAddToPool(PART_ID partId, char * pPool, unsigned
poolSize ) - add memory to a memory partition.
partId: partition to initialize
pPool pointer to memory block
poolSize block size in bytes
DESCRIPTION
This routine adds memory to a specified memory partition already
created with memPartCreate( ). The memory added need not be
contiguous with memory previously assigned to the partition.
RETURNS
OK or ERROR.
Example
#include"VxWorks.h"
#include"MemLib.h"
#include"stdio.h"
#include"taskLib.h"
#include"string.h"
void a(void);
void b(void);
PART_ID Id1;
char *p1;
void f()
{
unsigned int size=80;
void *p;
p=(void *)malloc(100);
Id1=memPartCreate((char *)p,size);
taskSpawn("task1",70,0,2000,(FUNCPTR)a,0,0,0,0,0,0,0,0,0,0);
taskSpawn("task2",80,0,2000,(FUNCPTR)b,0,0,0,0,0,0,0,0,0,0);
}
Example
void a(void)
{
p1=(char *)memPartAlloc(Id1,50);
strcpy(p1,"be proud to be indian");
printf("TASK1 writes \n");
}
void b(void)
{
printf("read data is %s \n",p1);
memPartFree(Id1,(void *)p1);
printf("TASK2 reads \n");
}
SIGNALS
Signals
Signals
A signal is the software analog of an interrupt:
A signal sent to a task indicates some asynchronous event has occurred.
There are 31 unique signals, each representing a different event.
A task can attach a signal handler to take appropriate action when the
signal is received.
Upon completion of signal handling, normal task execution is resumed
(unless the signal corresponds to an exception).
UNIX vs. VxWorks Signals
Signal is ignored if no handler is installed.
Can install a handler to catch SIGKILL.
No SIGCHLD, SIGPIPE, or SIGURG.
Automatic function restarting
Automatic function restarting describes behavior for a task which catches
a signal while on the pend queue:
1. Task receives a signal while pended.
2. Task is removed from pend queue and made ready to run.
3. When the task is the highest priority task on the Ready queue, it runs its
signal handler for the signal it caught.
4. After running its signal handler, the task is returned to the pended state,
with its originally specified timeout.
UNIX vs. VxWorks Signals
Caveats
Signals are not recommended for general inter task communication.
A signal:
◦ May be handled at too high priority if it arrives during a priority
inheritance.
◦ Disrupts a task‟s normal execution order. (It is better to create two
tasks than to multiplex processing in one task via signals.)
◦ Can cause reentrancy problems between a task running its signal
handler and the same task running its normal code.
◦ Can be used to tell a task to shut itself down.
Registering a Signal Handler
To register a signal handler:
signal (signo, handler)
signo Signal number.
handler Routine to invoke when signal arrives (or
SIG_IGN to ignore signal).
Returns the previously installed signal handler, or
SIG_ERR.
kill
Kill(int TASKID,INT SIGNO)
Kill function is used send any signal any task
Arguments
TASKID : ID of the task to which signal is to be sent
SIGNO : SIGNAL number to be sent
Signals and Exceptions
Hardware exceptions include bus error, address error, divide by
zero, floating point overflow, etc..
Some signals correspond to exceptions (e.g., SIGSEGV
corresponds to a bus error on a 68k; SIGFPE corresponds to
various arithmetical exceptions).
Signals and Exceptions
When an executing task generates an exception:
If the task has a signal handler installed to deal with that
exception, VxWorks will raise the signal to that task.
If the task has no signal handler installed for that exception,
VxWorks will suspend the task and log an error message to the
console.
Signals and Exceptions
If an exception signal handler returns:
The offending task will be suspended.
A message will be logged to the console.
/* function prototypes */
void catchSIGINT(int);
void sigCatcher(void);
/* globals */
#define NO_OPTIONS 0
#define ITER1 100
#define LONG_TIME 1000000
#define HIGHPRIORITY 100
#define LOWPRIORITY 101
int ownId;
Example
void sigGenerator(void) /* task to generate the SIGINT signal */
{
int i, j, taskId;
STATUS taskAlive;
if((taskId = taskSpawn("signal",100,0x100,20000,(FUNCPTR)sigCatcher,0,0,0,0,0,0,0,
0,0,0)) == ERROR)
printf("taskSpawn sigCatcher failed\n");
ownId = taskIdSelf(); /* get sigGenerator's task id */
taskDelay(30); /* allow time to get sigCatcher to run */
for (i=0; i < ITER1; i++)
{
if ((taskAlive = taskIdVerify(taskId)) == OK)
{
printf("+++++++++++++++++++++++++++++++SIGINT sinal generated\n");
kill(taskId, SIGINT); /* generate signal */
taskPrioritySet(ownId,LOWPRIORITY);
}
break;
}
printf("\n***************sigGenerator Exited***************\n");
}
void sigCatcher(void) /* task to handle the SIGINT signal */
{
struct sigaction newAction;
int i, j;
newAction.sa_handler = catchSIGINT; /* set the new handler */
sigemptyset(&newAction.sa_mask); /* no other signals blocked */
newAction.sa_flags = NO_OPTIONS; /* no special options */
if(sigaction(SIGINT, &newAction, NULL) == -1)
printf("Could not install signal handler\n");