Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 492 trang
THÔNG TIN TÀI LIỆU
Cấu trúc
ELEC371 CLASS NOTES- INTRODUCTION TO REAL-TIME OPERATING SYSTEMS (2001) by Robert Betz
Table of Contents
List of Figures
Chapter 1 INTRODUCTION TO OPERATING SYSTEMS
References
What is an Operating system?
What is Multi-programming?
Why were Multi-programming Systems Developed?
Definition of an Operating System
Types of Operating Systems
Some more definitions – Processors, Programs and Tasks
Hierarchical Structure of Operating Systems.
A digression – the role of interrupts in Operating Systems.
What is an interrupt?
Why are interrupts crucial to Operating Systems?
Example: Producer-Consumer Problem
Chapter 2 PRINCIPLES OF SOFTWARE DESIGN
Problems with Real Time Design
Some Suggestions on Program Structure
The efficiency trap
Chapter 3 OVERVIEW OF MULTI-TASKING
Coroutines
Tasks
Anatomy of an Operating System Kernel
The Dispatcher
Synchronization Primitives
Protected and Non-protected Operating Systems
Brief Discussion of Memory Management
Brief Discussion of Supervisor Mode
Chapter 4 SEMAPHORES
Basic Concepts
Wait and Signal
Semaphores as Resource Counters
Task Synchronization
Consumer-Producer Problem Revisited
More Complex Synchronization Problems
Multiple unit resource allocation
Dining philosophers problem
Readers and Writers problem
Variations on the semaphore
Logic semaphores
Timed semaphores, sleeping tasks and simulated task suspension
Semaphores and priorities
Other synchronization primitives
Event primitives
Monitors
A practical semaphore structure
Deadlock and Starvation
Resource types
Reusable resources
Consumable resources
The conditions for deadlock
Techniques to handle deadlock
Deadlock prevention
Deadlock detection
Deadlock avoidance
Task initiation denial:
Resource Allocation Denial:
Summarizing
Chapter 5 TASK MANAGEMENT
Task descriptors
Kernel Queues
Description of UNOS-V1.5
Unos-V1.5 Task Control Block (TCB) and Semaphore Structures
Queue Operation in UNOS-V1.5
UNOS-V1.5 task creation
The Dispatcher
The UNOS-V1.5 Dispatcher
The task switch operation
The UNOS-V1.5 task switch
Subtasks and Interrupt Tasks
Time-slicing
Unos time slicing
Task suspension
Dynamic Priorities
Definitions Useful for Priority Inheritance
A General Priority Inheritance Algorithm
An Implementation of Priority Inheritance
Some Explicit Implementations
The Inherit1 Algorithm
The Inherit2 Algorithm
The Inherit3 Algorithm
Interesting Benefit
Higher Order Scheduling
Some Definitions and Background
Basic Rate-Monotonic Analysis
Fundamental Results
Rate-Monotonic Scheduling
Utilisation Bound
Completion Time Test
Deadline-Monotonic Scheduling
Relaxing the Assumptions – Generalised Rate-Monotonic Analysis
Task Synchronisation
Release Jitters
Arbitrary Deadlines
Chapter 6 TASK COMMUNICATION AND TIMING
Intertask Communications
Common Data Buffer Technique
Circular Buffer Technique
Mail Box Technique
Pointer Transfer Technique
Examples of Intertask Communication in Some Real Operating Systems
Unix
UNOS
Timing in Real-time Systems
Time Delays
UNOS timers
UNOS timer creation
UNOS timer queues
UNOS timer maintenance routines
UNOS user interface routines
UNOS timed semaphore wait
Applications of UNOS timers
UNOS Heap Management
Chapter 7 INTERRUPTS
Basic interrupt mechanism
Finer details of the interrupt mechanism
Hardware structure of interrupts
Other types of interrupts
Interrupt priorities
Interrupt tasks
Interrupt handlers and the dispatcher
Relaxing the “no task switch” condition
Chapter 8 DEVICE DRIVERS
What is a device driver?
Structure of a device driver
Design objectives and implications
Anatomy of an I/O request
The device handler
Buffering
Issues related to efficiency
Chapter 9 AN INTRODUCTION TO FILE SYSTEMS
Logical Structure of File Systems
Basic Implementation
Sequential Files
Indexed Sequential Access Method (ISAM)
Indexed file
Directories
Symbolic Naming
Access Rights
Physical Structure of File Systems
Physical Structure of Disks
Disk allocation table
Record blocking
File allocation table
Some examples
MS-DOS file allocation
FAT32 File System
UNIX file allocation
Miscellaneous File System Issues
Links
File System Consistency
Real-time issues
Chapter 10 VIRTUAL MEMORY AND PROTECTION
Virtual addressing - basic concepts.
Virtual memory models
Segmentation - basic principles
Paging - basic principles
Some implementation issues
The best of both worlds - combined paging and segmentation
Chapter 11 CASE STUDY - THE 80386-DX PROCESSOR
Application Programmer’s Register Model
System Programmer’s Register Model
System Flags
Memory-Management Registers
Control Registers
Segmented Address Models in the 80386
Flat Model
Protected Flat Model
Multi-Segment Model
Segment Translation in the 80386
Segment Selectors
Segment Descriptors
Paging in the 80386
Translation Lookaside Buffer.
Combined Segment and Page Translation
The Flat Paging Model – Getting rid of Segmentation
Segmentation and Paging Together
Protection in the 80386 Processor
Segment-level Protection
Segment Descriptors and Protection
Type Checking
Limit Checking
Privilege Levels
Restricting Access
Restricting Access to Data
Restricting Control Transfers
Gate Descriptors
Stack Switching
Returning from a Procedure
Pointer Validation
Descriptor Validation
Pointer Integrity and RPL
Page Level Protection
Restriction of Addressable Domain
Multitasking Support in the 80386
Task State Segment
TSS Descriptor
Task Register
Task Gate Descriptor
Task Switching
Task Linking
Busy Bit
Task Address Space
Protected Input/Output
I/O Addressing in the 80386
Protection and I/O
I/O Privilege Level
I/O Permission Bit Map
Conclusion
Appendix A UNOS-V2.0 TUTORIAL
Introduction
General Layout of UNOS Based Software
Detailed Example of the Use of UNOS
The Main Module
The Initunos Module
Usertask Module
Task Modules
Task0 Module
Task1 Module
Task 2 Module
Header Files
unos.h
general.h
Common Header Files for User Tasks
comdec.h
pcscrn.h
tasks.h
time.h
Other important header files
hwpc.h
config_os.h
Appendix B A SIMPLE WINDOW SYSTEM
Introduction
User Functions
How to Use the Windowing System
A Note on Setting Character Attributes
Reference Section
The Point Class
POINT::POINT DESCRIPTION
POINT::OPERATOR= DESCRIPTION
POINT::MOVETO DESCRIPTION
POINT::SET_ATTRIBUTES DESCRIPTION
POINT::WRITE_TO_PT DESCRIPTION
POINT::RETURN_ATTRIBUTES
The Screen Class
SCREEN::SCREEN DESCRIPTION
SCREEN::PRINT DESCRIPTION
SCREEN::CLR_LINE DESCRIPTION
SCREEN::CLR_EOL DESCRIPTION
SCREEN::CLR_BOL DESCRIPTION
SCREEN::CLR_SCR DESCRIPTION
SCREEN::SET_SCRN_BACKGRD DESCRIPTION
SCREEN::DRAW_BOX DESCRIPTION
SCREEN::DRAW_HORIZ_LINE DESCRIPTION
SCREEN::DRAW_VERT_LINE DESCRIPTION
SCREEN::SCROLL DESCRIPTION
Window Class
WINDOW::WINDOW DESCRIPTION
WINDOW::CLEAR_WINDOW DESCRIPTION
WINDOW::SET_WINDOW_BACKGRD_COLOUR DESCRIPTION
WINDOW::PAINT_WINDOW_BACKGRD DESCRIPTION
WINDOW::GO_WINDOW_XY DESCRIPTION
WINDOW::PRINT DESCRIPTION
WINDOW::PRINT DESCRIPTION
WINDOW::SET_STRING_COLOUR DESCRIPTION
WINDOW::SET_STRING_BACKGRD_COLOUR DESCRIPTION
WINDOW::SCROLL_WINDOW DESCRIPTION
WINDOW::WINDOW_CLEAR_LINE DESCRIPTION
WINDOW::GET_TOP/BOT_LEFT/RIGHT/XY DESCRIPTIONS
WINDOW::DRAW_HORIZ_LINE DESCRIPTION
WINDOW::DRAW_VERT_LINE DESCRIPTION
Appendix C UNOS-V2.0 REFERENCE MANUAL
INTRODUCTION
KEY FEATURES
REAL-TIME SERVICES
HARDWARE REQUIREMENTS
INTRODUCTION TO UNOS-V2.0 KERNEL PRIMITIVES
Kernel Initialisation
setup_os_data_structures
Task Management
create_task
change_task_priority
rtn_task_priority
start_tasks
rtn_current_task_num
rtn_current_task_name_ptr
chg_task_tick_delta
Task scheduling management
preemptive_schedule
reschedule
start_time_slice
stop_time_slice
chg_base_ticks_per_time_slice
Time management
create_timer
start_timer
reset_timer
stop_timer
Intertask communication and synchronization
create_semaphore
init_semaphore
wait
timed_wait
usignal
return_semaphore_value
create_lock
lock
unlock
send_mess
send_qik_mess
rcv_mess
size_mbx
size_mbx_mess
free_mbx
used_mbx
flush_mbx
Memory Management
umalloc
ucalloc
ufree
ret_free_mem
Miscellaneous
return_interrupt_status
DETAILED DESCRIPTION OF USER INTERFACE
Kernel Initialisation Functions
SETUP_OS_DATA_STRUCTURES DESCRIPTION
Task Management Functions
CREATE_TASK DESCRIPTION
CHANGE_TASK_PRIORITY DESCRIPTION
RTN_TASK_PRIORITY DESCRIPTION
START_TASKS DESCRIPTION
RTN_CURRENT_TASK_NUM DESCRIPTION
RTN_CURRENT_TASK_NAME_PTR DESCRIPTION
CHG_TASK_TICK_DELTA DESCRIPTION
Task Scheduling Management Functions
PREEMPTIVE_SCHEDULE DESCRIPTION
RESCHEDULE DESCRIPTION
START_TIME_SLICE DESCRIPTION
STOP_TIME_SLICE DESCRIPTION
CHG_BASE_TICKS_PER_TIME_SLICE DESCRIPTION
Time Management Functions
CREATE_TIMER DESCRIPTION
START_TIMER DESCRIPTION
RESET_TIMER DESCRIPTION
STOP_TIMER DESCRIPTION
Intertask Communication and Synchronization Functions
CREATE_SEMAPHORE DESCRIPTION
INIT_SEMAPHORE DESCRIPTION
WAIT DESCRIPTION
TIMED_WAIT DESCRIPTION
USIGNAL DESCRIPTION
RETURN_SEMAPHORE_VALUE DESCRIPTION
CREATE_LOCK DESCRIPTION
LOCK DESCRIPTION
UNLOCK DESCRIPTION
DESTROY_LOCK DESCRIPTION
SEND_MESS DESCRIPTION
SEND_MESS MACRO DESCRIPTION
SEND_MESS_NB MACRO DESCRIPTION
SEND_QIK_MESS DESCRIPTION
RCV_MESS DESCRIPTION
SIZE_MBX DESCRIPTION
SIZE_MBX_MESS DESCRIPTION
FREE_MBX DESCRIPTION
USED_MBX DESCRIPTION
FLUSH_MBX DESCRIPTION
Memory Management Functions
UMALLOC DESCRIPTION
UCALLOC DESCRIPTION
UFREE DESCRIPTION
RET_FREE_MEM DESCRIPTION
Miscellaneous Functions
RETURN_INTERRUPT_STATUS DESCRIPTION
Appendix D THE KEYBOARD SYSTEM
Introduction
Organisation and Use
Appendix E UNOS SERIAL HANDLERS
INTRODUCTION
USER INTERFACE
SETTING UP AND USING THE SERIAL CHANNELS
The header files
USER INTERFACE DESCRIPTION
CREATE_SERIAL DESCRIPTION
Appendix F COMMAND DECODER
Introduction
Basic Data Structures
Decoder Tables - How to use them
Example
Appendix G UNOS ALARM HANDLING
Features
Data structures used in the Alarm System
The Alarm Number Array
The Alarm Structure.
Ancillary Data Structures
Low Level User Interface to the Alarm System
finCreateAlarm Description
fulgAlarm Description
fulgRetNumUnresetAlarms Description
fulgResetAlarm Description
fvdStopConseqSuppr Description
fulgResetAllAlarmsClearOnce Description
fulgRetCumulAlarms Description
finRetCumulStartTimeDate Description
finRetFirstUnresetAlarmTimeDate Description
finRetLastUnrestAlarmTimeDate Description
finClearCumulAlarms Description
Some Notes About Usage
Appendix H UNOS-V2.0 LISTING
CONDITIONS OF USE OF THE UNOS KERNEL
MISCELLANEOUS INFORMATION
FULL KERNEL LISTING
BIBLIOGRAPHY
Nội dung
(/(& &/$66 127(6 ,1752'8&7,21 72 5($/7,0( 23(5$7,1* 6mess_addr = task_num; mbx_ptr->mbx_type = mbx_type; mbx_ptr->q_size = num_mess; H-83 Appendix H — UNOS-V2.0 LISTING mbx_ptr->mess_size = mess_size; mbx_ptr->spce_avail_sema = spce_avail_sema; mbx_ptr->mess_avail_sema = mess_avail_sema; mbx_ptr->free = num_mess; mbx_ptr->used = 0; mbx_ptr->get_ptr = 0; mbx_ptr->put_ptr = 0; mbx_ptr->qik_mess_flag = FALSE; /* now allocate the quick message envelope */ mbx_ptr->qik_mess_ptr = ( envelope* )umalloc ( sizeof ( envelope ) ); /* now allocate the message queue envelopes */ mbx_ptr->mess_q_ptr =( envelope* )ucalloc ( num_mess, sizeof ( envelope ) ); /* check to see if the allocation for the envelopes has been successful */ if ( ( mbx_ptr->qik_mess_ptr == NULL_PTR ) || ( mbx_ptr->mess_q_ptr == NULL_PTR ) ) return ( mbx* )NULL_PTR; /* now allocate the message buffers for each of the envelope structures */ mbx_ptr->qik_mess_ptr->message_ptr = ( char* )ucalloc ( mess_size, sizeof ( char ) ); for ( i = 0; i < num_mess; i++ ) { mbx_ptr->mess_q_ptr [ i ].message_ptr = ( char* )ucalloc ( mess_size, sizeof ( char ) ); if ( mbx_ptr->mess_q_ptr [ i ].message_ptr == NULL_PTR ) allocation_problem = TRUE; } /* for */ /* now check if the allocation of the message buffers for each of the envelopes has been successful */ if ( ( mbx_ptr->qik_mess_ptr->message_ptr == NULL_PTR ) || allocation_problem ) return ( mbx* )NULL_PTR; else return mbx_ptr; } /* if */ else { cprintf ( “Mail Box allocation problem\n” ); return ( mbx* )NULL_PTR; } /* else */ } /* end create_mbx */ /* -*/ /* ============================================================================ | | mail_exchange | | The purpose of this function is to match the pointer to a task name to the | task number This matching operation is required in the mail system to | allow the address of a task to be independent of its task number The | mapping from the pointer value to the task number is implemented using | a chained hashing algorithm The hash table is initialised during the H-84 FULL KERNEL LISTING | task creation process The hash table itself contains pointers to linked | lists of taskname_map structures The index into the table is calculated | using a simple (but effective) modulus based hashing scheme | | If the pointer address hashes to a table entry which has no taskname_map | structure pointer then one is attempting to send data to an undefined | task This is indicated by a hash_table entry being NULL_PTR The routine | in this case returns the task number as the contents of num_of_tasks | (which is actually one more than the number of the last task number) | | Parameter :- pointer to a character string | | Entry via :- send_mess function | ============================================================================ */ static unsigned int mail_exchange ( char *mess_addr_ptr ) { unsigned int hash_table_index; taskname_map *taskname_struc_ptr; unsigned int task_number = 0xffff; /* firstly hash the pointer */ hash_table_index = hash_taskname_ptr ( mess_addr_ptr ); /* now look into the hash table */ if ( hash_table [ hash_table_index ] != NULL_PTR ) { taskname_struc_ptr = hash_table [ hash_table_index ]; { if ( taskname_struc_ptr->task_name_ptr == mess_addr_ptr ) { task_number = taskname_struc_ptr->task_number; taskname_struc_ptr = NULL_PTR; } /* if */ else { taskname_struc_ptr = taskname_struc_ptr->nxt_taskname_map; } /* else */ } while ( taskname_struc_ptr != NULL_PTR ); } /* if */ /* now check to see if a legal task number has been found */ if ( task_number == 0xffff ) { /* illegal task number found */ return num_of_tasks; } /* if */ else { return task_number; } /* else */ } /* end of mail_exchange */ /* -*/ /* H-85 Appendix H — UNOS-V2.0 LISTING ============================================================================== | | send_mess | | This function puts a message into a mail box for a particular task The | can be called in two modes - blocking mode and non-blocking mode In blocking | mode if the mail box is full then the calling task is blocked on a semaphore | In non-blocking mode, if the mail box is full then control is returned to | the calling task, along with a return code to indicate that the message was | not sent (FULL_MBX) | | In order to make the address of the message independent of task numbering | message addresses consist of a pointer to a string describing the task The | connection between this pointer and the task number is created at task | creation time In order to make it fast to obtain the task number from | the string pointer a hash table is used This mapping is carried out by the | mail exchange which implements a chained hashing algorithm | | NOTE : this routine currently does not handle priority mail boxes | | Note that interrupts are disabled for a large part of this routine in order | to make the message indivisible | | Parameters : - pointer to the message to be sent | - length of the message to be sent | - address of the receiver of the message This is a pointer to | a character string that contains the name of the task The | pointer value is actually used as address of the task and | the contents of the character string | - a number indicating whether the caller should be blocked or | not on the mail box semaphore A zero indicates that the | caller should be blocked (BLOCK_SM), a one indicates that | if the mail box is full then control should be returned to | the caller (NO_BLOCK_SM) | | Returns: - a TRUE if the message is successfully sent | - a FALSE if the message is too big for the mail box, or an | attempt is made to send a message to a non-existent task | - a FULL_MBX is returned if the mailbox is full and the routine | is called with the block_action parameter set to NO_BLOCK_SM | | Entry via : - multiple places | ============================================================================== */ int send_mess ( unsigned char* mess_ptr, unsigned int mess_lgth, char *mess_addr_ptr, int block_action ) { unsigned int mess_addr, sender_task_num; char *sender_addr_ptr; char int_status; unsigned int i; /* firstly call the mail exchange to establish which task number is being addressed, and then check to see if the task that the message is being sent to actually exists If it doesn’t then return with a FALSE */ if ( ( ( mess_addr = mail_exchange ( mess_addr_ptr ) ) >= num_of_tasks)) { return FALSE; /* non-existent task being addressed */ } /* if */ /* now check whether the message will fit in the message buffer */ if ( mess_lgth > mbx_table [ mess_addr ]->mess_size ) return FALSE; /* does not fit in the message buffer */ int_status = return_interrupt_status ( ); disable ( ); H-86 FULL KERNEL LISTING /* Now check whether this should block or not */ if (block_action == NO_BLOCK_SM) { /* No blocking allowed so check to see if the mail box has space */ if ( mbx_table [ mess_addr ]->spce_avail_sema == ) { /* Will get blocked so return with a return code */ if (int_status) { enable (); } /* if */ return (FULL_MBX); } /* if */ } /* if */ /* Enter at this point if the call is a blocking call, or the calling task will not get blocked */ wait ( mbx_table [ mess_addr ]->spce_avail_sema ); sender_task_num = rtn_current_task_num ( ); /* now get the name of the sending task by looking in the tcb of the task */ sender_addr_ptr = tcb [ sender_task_num ]->task_name_ptr; /* copy the message into the correct mail box envelope */ for ( i = 0; i < mess_lgth; i++ ) mbx_table [ mess_addr ]->mess_q_ptr [ mbx_table [ mess_addr ]->put_ptr ].message_ptr [ i ] = mess_ptr [ i ]; /* now complete the rest of the envelope structure */ mbx_table [ mess_addr ]->mess_q_ptr [ mbx_table [ mess_addr ]->put_ptr ] mess_lgth = mess_lgth; mbx_table [ mess_addr ]->mess_q_ptr [ mbx_table [ mess_addr ]->put_ptr ] rtn_addr_ptr = sender_addr_ptr; mbx_table [ mess_addr ]->mess_q_ptr [ mbx_table [ mess_addr ]->put_ptr ] sender_pri = tcb [ sender_task_num ]->priority; /* now update the mail box accounting locations */ mbx_table [ mess_addr ]->put_ptr++; if ( mbx_table [ mess_addr ]->put_ptr >= mbx_table [ mess_addr ]->q_size ) mbx_table [ mess_addr ]->put_ptr = 0; mbx_table [ mess_addr ]->free ; mbx_table [ mess_addr ]->used++; if ( int_status ) enable ( ); usignal ( mbx_table [ mess_addr ]->mess_avail_sema ); return TRUE; /* indicate that message successfully sent */ } /* end of send_mess */ /* */ /* H-87 Appendix H — UNOS-V2.0 LISTING ========================================================================== | | send_qik_mess | | This function sends a quick message to a mail box for a particular task | A quick or express message is different from a normal message in that | it should be the next message read from the mail box regardless of the | other messages that may be stored in the mail box This is generally | achieved by putting the quick message just prior to the next message to | be read from the buffer and then adjusting the get_ptr appropriately | If the message queue is full however this cannot be done, and in fact the | task generating the message could become blocked (depending on how this | situation was handled) For this reason the mail box contains a special | envelope to store quick messages If the situation arises where the special | mail box is full also then the routine returns immediately with a return | code equal to which indicates this condition A return code of (usually | corresponding to a FALSE) indicates that the message is too big for the | size of the message buffers A return code of (usually corresponding to | a TRUE) indicates a successful message sent | | Parameters : - pointer to the message to be sent | - message length | - address where message is to be sent - a pointer to the | task name | | Entry via : - multiple places | =========================================================================== */ int send_qik_mess ( unsigned char* mess_ptr, unsigned int mess_lgth, char * mess_addr_ptr ) { char int_status; unsigned int mess_addr, i; /* firstly call the mail exchange to establish which task number is being addressed, and then check to see if the task that the message is being sent to actually exists If it doesn’t then return with a FALSE */ if ( ( ( mess_addr = mail_exchange ( mess_addr_ptr ) ) >= num_of_tasks)) { return FALSE; /* non-existent task being addressed */ } /* if */ /* check if the message will fit in the message buffer */ if ( mess_lgth > mbx_table [ mess_addr ]->mess_size ) { return FALSE; /* message too big for the buffer */ } /* if */ int_status = return_interrupt_status ( ); disable ( ); /* now check to see if there is room in the normal message queue for the express message */ if ( mbx_table [ mess_addr ]->free == ) { /* enter here if there is no room in the normal message buffer so now check to see if there is room in the special qik message buffer If there is no room here then return with the appropriate return code */ if ( mbx_table [ mess_addr ]->qik_mess_flag ) { /* qik message envelope full so reset interrupts and return to the calling program */ if ( int_status ) H-88 FULL KERNEL LISTING enable ( ); return 2; } /* if */ else { /* there is room in the qik message envelope */ for ( i = 0; i < mess_lgth; i++ ) mbx_table [ mess_addr ]->qik_mess_ptr->message_ptr [ i ] = mess_ptr [ i ]; mbx_table [ mess_addr ]->qik_mess_ptr->rtn_addr_ptr = tcb [ rtn_current_task_num ( )]->task_name_ptr; mbx_table [ mess_addr ]->qik_mess_ptr->sender_pri = tcb [ mess_addr ]->priority; mbx_table [ mess_addr ]->qik_mess_ptr->mess_lgth = mess_lgth; mbx_table [ mess_addr ]->qik_mess_flag = TRUE; } /* else */ } /* if */ else { /* there are free locations in the message queue so put the qik message at the head if this queue If the message queue is empty then put the message in it at the put_ptr location */ if ( mbx_table [ mess_addr ]->used == ) { /* now write the message into the envelope in the envelope queue */ for ( i = 0; i < mess_lgth; i++ ) mbx_table [ mess_addr ]->mess_q_ptr [ mbx_table [ mess_addr ]->put_ptr ].message_ptr [ i ] = mess_ptr [ i ]; /* now update the other components of the envelope */ mbx_table [ mess_addr ]->mess_q_ptr [ mbx_table [ mess_addr ]->put_ptr ].rtn_addr_ptr = tcb [ rtn_current_task_num ( ) ]->task_name_ptr; mbx_table [ mess_addr ]->mess_q_ptr [ mbx_table [ mess_addr ]->put_ptr ].sender_pri = tcb [ mess_addr ]->priority; mbx_table [ mess_addr ]->mess_q_ptr [ mbx_table [ mess_addr ]->put_ptr ].mess_lgth = mess_lgth; mbx_table [ mess_addr ]->put_ptr++; if ( mbx_table [ mess_addr ]->put_ptr >= mbx_table [ mess_addr ]->q_size ) mbx_table [ mess_addr ]->put_ptr = 0; } /* if */ else { if ( mbx_table [ mess_addr ]->get_ptr == ) mbx_table [ mess_addr ]->get_ptr = mbx_table [ mess_addr ]-> q_size - 1; else mbx_table [ mess_addr ]->get_ptr ; /* now write the message into the envelope in the envelope queue */ for ( i = 0; i < mess_lgth; i++ ) mbx_table [ mess_addr ]->mess_q_ptr [ mbx_table [ mess_addr ]-> get_ptr ].message_ptr [ i ] = mess_ptr [ i ]; /* now update the other components of the envelope */ mbx_table [ mess_addr ]->mess_q_ptr [ mbx_table [ mess_addr ]->get_ptr ].rtn_addr_ptr = tcb [ rtn_current_task_num ( ) ]->task_name_ptr; mbx_table [ mess_addr ]->mess_q_ptr [ mbx_table [ mess_addr ]->get_ptr ].sender_pri = tcb [ mess_addr ]->priority; mbx_table [ mess_addr ]->mess_q_ptr [ mbx_table [ mess_addr ]->get_ptr ].mess_lgth = mess_lgth; } /* else */ H-89 Appendix H — UNOS-V2.0 LISTING /* now update the used and free locations */ mbx_table [ mess_addr ]->free ; mbx_table [ mess_addr ]->used++; } /* else */ if ( int_status ) enable ( ); /* now signal that data is available in the mail box */ usignal ( mbx_table [ mess_addr ]->mess_avail_sema ); return TRUE; } /* end of send_qik_mess */ /* -*/ /* ============================================================================= | | rcv_mess | | This routine receives a message from a mail box associated with a particular | task There is no need to specify the mail box since the mail box from | which the message is read from is that associated with the task | One important feature of this routine is that the receiving task can | indicate how long it will wait for the message by passing a time limit to the | routine If a value of zero is passed for the time limit then the time limit | is deemed to be infinite | | The function returns the address of the sending task if the timeout period | has not expired Note that this address is returned as a pointer to the | character string which names the task If the timeout period has expired | without a message being received it will return NULL_PTR If the return is | due to the fact that a timer is not available for the timed_wait operation | then the return code is 0xffff:000f | | Parameters : - pointer to the memory area where the message will be stored | - pointer to the integer where the message length will be | stored | - time limit value | | Entry via : - multiple places | ============================================================================= */ char *rcv_mess ( unsigned char* mess_ptr, unsigned int* mess_lgth, unsigned long time_limit ) { unsigned int mbx_addr; char *rtn_addr_ptr; int wait_result = 0; char int_status; unsigned int i; unsigned int *mess_lgth_ptr; char *qik_mess_ptr; char *mbx_mess_ptr; mbx_addr = rtn_current_task_num ( ); H-90 FULL KERNEL LISTING /* firstly check what type of wait has to be carried out */ if ( time_limit == ) wait ( mbx_table [ mbx_addr ]->mess_avail_sema ); else wait_result = timed_wait ( mbx_table [ mbx_addr ]-> mess_avail_sema, time_limit ); /* now check the value of the wait_result If zero then the wait has been terminated by a signal condition or no wait has occurred If the wait result is non-zero then some error condition has occurred the type of error condition is determined by the value:- 1=>wait terminated due to a timeout on the semaphore; 2=>a timer was not available for the timed_wait */ if ( wait_result ) { if ( wait_result == ) return NULL_PTR; /* timeout occurred */ return ( (char*)MK_FP ( 0xffff, 0x000f ) ); /* no timer available */ } /* if */ int_status = return_interrupt_status ( ); disable ( ); /* enter this section of the code if there is a message to receive Now check to see if the message is in the qik message envelope If so then retrieve it from there, else get the message from the message envelope queue */ if ( mbx_table [ mbx_addr ]->qik_mess_flag ) { /* message in the qik envelope */ /* now setup pointers to the appropriate variables so that the compiler will be forced to produce efficient code */ mess_lgth_ptr = &mbx_table [ mbx_addr ]->qik_mess_ptr->mess_lgth; qik_mess_ptr = mbx_table [ mbx_addr ]->qik_mess_ptr->message_ptr; for ( i = 0; i < *mess_lgth; i++ ) { mess_ptr [ i ] = *(qik_mess_ptr + i); } /* for */ *mess_lgth = *mess_lgth_ptr; mbx_table [ mbx_addr ]->qik_mess_flag = FALSE; rtn_addr_ptr = mbx_table [ mbx_addr ]->qik_mess_ptr->rtn_addr_ptr; } /* if */ else { /* message must be in the normal message queue so retrieve from here */ /* firstly assign the key variables to pointers to force the compiler to produce efficient code */ mess_lgth_ptr = &mbx_table [ mbx_addr ]->mess_q_ptr [ mbx_table [ mbx_addr ]->get_ptr ].mess_lgth; mbx_mess_ptr = mbx_table [ mbx_addr ]->mess_q_ptr [ mbx_table [ mbx_addr ]->get_ptr ].message_ptr; for ( i = 0; i < *mess_lgth_ptr; i++ ) { mess_ptr [ i ] = *(mbx_mess_ptr + i); } /* for */ *mess_lgth = mbx_table [ mbx_addr ]->mess_q_ptr [ mbx_table [ mbx_addr ]->get_ptr ].mess_lgth; rtn_addr_ptr = mbx_table [ mbx_addr ]->mess_q_ptr [ mbx_table [ mbx_addr ]->get_ptr ].rtn_addr_ptr; mbx_table [ mbx_addr ]->get_ptr++; if ( mbx_table [ mbx_addr ]->get_ptr >= mbx_table [ mbx_addr ]-> q_size ) H-91 Appendix H — UNOS-V2.0 LISTING { mbx_table [ mbx_addr ]->get_ptr = 0; } /* if */ mbx_table [ mbx_addr ]->free++; mbx_table [ mbx_addr ]->used ; } /* else */ /* now signal that space is available in the mail box */ usignal ( mbx_table [ mbx_addr ]->spce_avail_sema ); if ( int_status ) enable ( ); return rtn_addr_ptr; } /* end of rcv_mess */ /* */ /* ============================================================================= | | size_mbx | | This function returns the size of the message queue for a particular mail | box If one tries to look at an illegal mail box then a zero is returned, | else the size of the mail box is returned | | Parameters : - mail box address - which is the task name with which it is | associated | | Entry via : - multiple places | ============================================================================= */ unsigned int size_mbx ( char *mbx_addr_ptr ) { unsigned int mbx_num; unsigned int mbx_size; /* carry out the mapping between the mail box name (which is the task name) and the mail box number */ if ( ( mbx_num = mail_exchange ( mbx_addr_ptr ) ) >= num_of_tasks ) { /* trying to look at an illegal mail box */ mbx_size = 0; } /* if */ else { /* address OK */ mbx_size = mbx_table [ mbx_num ]->q_size; } /* else */ return mbx_size; } /* end of size_mbx */ H-92 FULL KERNEL LISTING /* */ /* ============================================================================= | | size_mbx_mess | | This function returns the maximum size of a message which can be sent to a | mail box (i.e the size of each of the message slots in the message queue | If the mail box address is illegal then the routine returns a value of | 0, else the length of the messages is returned | | Parameters : - address of the mail box (i.e task name with which it is | associated) whose size is to be determined | | Entry via : - multiple places | ============================================================================= */ unsigned int size_mbx_mess ( char *mbx_addr_ptr ) { unsigned int mbx_num; unsigned int size_mbx_mess; /* carry out the mapping between the mail box name (which is the task name) and the mail box number */ if ( ( mbx_num = mail_exchange ( mbx_addr_ptr ) ) >= num_of_tasks ) { /* trying to look at an illegal mail box */ size_mbx_mess = 0; } /* if */ else { /* address OK */ size_mbx_mess = mbx_table [ mbx_num ]->mess_size; } /* else */ return size_mbx_mess; } /* end of size_mbx_mess */ /* -*/ /* ============================================================================== | | free_mbx | | This function returns the number of free message slots in a mail box If | the mail box number is illegal then the routine returns a 0xffff value, else | it returns the number of free locations | | Parameters : - address of the mail box (i.e task name pointer with which | it is associated) whose free space is to be determined H-93 Appendix H — UNOS-V2.0 LISTING | | Entry via : - multiple places | ============================================================================= */ unsigned int free_mbx ( char *mbx_addr_ptr ) { char int_status; unsigned int mbx_num; unsigned int free; int_status = return_interrupt_status ( ); disable ( ); /* carry out the mapping between the mail box name (which is the task name) and the mail box number */ if ( ( mbx_num = mail_exchange ( mbx_addr_ptr ) ) >= num_of_tasks ) { /* trying to look at an illegal mail box */ free = 0xffff; } /* if */ else { /* address OK */ free = mbx_table [ mbx_num ]->free; } /* else */ if ( int_status ) enable ( ); return free; } /* end of free_mbx */ /* -*/ /* ============================================================================== | | used_mbx | | This function returns the number of used message slots in a mail box If the | mail box number is illegal then the number returned is 0xffff | | Parameters : - address of the mail box (i.e the task nmae pointer with | which the mail box is associated) whose used space is to | be determined | | Entry via : - multiple places | ============================================================================== */ unsigned int used_mbx ( char *mbx_addr_ptr ) { char int_status; unsigned int mbx_num; unsigned int used; int_status = return_interrupt_status ( ); disable ( ); H-94 ... this to be an example of a real time operating system Engineers on the other hand would not consider this to a a real time operating system A real time operating system to an engineer has hard time. .. Chapter — INTRODUCTION TO OPERATING SYSTEMS The static/dynamic classification often corresponds to the real time/ non -real time as described above Real time applications of operating systems are... operating systems • non -real time operating systems There is some debate as to what constitutes a real time operating system For example, is an airline booking system a real time operating system?