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
Thông tin cơ bản
Định dạng
Số trang
492
Dung lượng
3,73 MB
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?