/**********************************************************************/ /* Howard Eng 2/94 */ /* Unixpros, Inc */ /* */ /* This module is used to keep track of existing tasks. For every */ /* task that is created it is added to two lists. One list contains */ /* the task's handle. The other uses the task's TCB as the search */ /* key. This is required to determine a task's handle from the */ /* current TCB. */ /**********************************************************************/ #include #include #include "ada_cma_lib.h" #include "ada_ptd_exc.h" #include "tree.h" #undef cma__int_init typedef struct { char *task_rec; char *tcb_id; } task_data_t; static tree *master_task_lst; static tree *master_handle_lst; static int compare_task_handles ( node, data ) tree *node; char *data; { return ( ((long) data) - ((long) node->data) ); } static int compare_tasks ( node, data ) tree *node; task_data_t *data; { task_data_t *node_data; int answer; node_data = (task_data_t *) node->data; if( data->tcb_id < node_data->tcb_id ) answer = -1; else if( data->tcb_id == node_data->tcb_id ) answer = 0; else answer = 1; return ( answer ); } static char *task_mgr_lock; static char *create_lock () { extern char *cma__get_mutex( char *) ; task_mgr_lock = cma__get_mutex( (char *) NULL ); } /**********************************************************************/ /* Adds a new task to the master list. The task is stored according */ /* to the tcb_id. */ /**********************************************************************/ void ada_thd_add_task_to_list ( task_rec, tcb_id ) char *task_rec; char *tcb_id; { task_data_t *data; static pthread_once_t once_block = pthread_once_init; pthread_once( &once_block, (pthread_initroutine_t) create_lock); data = (task_data_t *) malloc( sizeof( task_data_t ) ); if( data != (task_data_t *) NULL ) { data->task_rec = task_rec; data->tcb_id = tcb_id; cma__int_lock( task_mgr_lock ); ada_thd_add_to_tree( &master_task_lst, (char *) data, ( int (*)( tree *, void *) ) compare_tasks); ada_thd_add_to_tree( &master_handle_lst, (char *) task_rec, ( int (*)( tree *, void *) ) compare_task_handles ); cma__int_unlock( task_mgr_lock ); } } char *ada_thd_retrieve_handle ( handle ) char *handle; { char *data; cma__int_lock( task_mgr_lock ); data = (char *) ada_thd_get_from_tree( master_handle_lst, (char *) handle, (int (*)(tree *, void * )) compare_task_handles ); cma__int_unlock( task_mgr_lock ); return ( data ); } /**********************************************************************/ /* Given a tcb_id, returns the task id or NULL if the tcb_id doesn't */ /* exist. */ /**********************************************************************/ char *ada_thd_get_from_task_list ( tcb_id ) char *tcb_id; { task_data_t *found; task_data_t item; item.tcb_id = tcb_id; if( task_mgr_lock != (char *) NULL ) cma__int_lock( task_mgr_lock ); found = (task_data_t *) ada_thd_get_from_tree( master_task_lst, (char *) &item, (int (*)(tree *, void * )) compare_tasks ); if( task_mgr_lock != (char *) NULL ) cma__int_unlock( task_mgr_lock ); return ( found != (task_data_t *) NULL ? found->task_rec : (char *) NULL ); } /**********************************************************************/ /* Replaces the normal "pthread" routine. This function returns the */ /* TCB pointer that is stored within the task control record. The two*/ /* static variables are the "allocated" tcb and exception stack for */ /* the main thread. */ /**********************************************************************/ #include #include typedef struct { cma__t_int_tcb cma_tcb; exc_context_t exc_stack; } tcb_t; static tcb_t main_thread_cma_tcb; cma__t_int_tcb *cma__get_self_tcb () { tcb_t *tcb; extern tcb_t *ada_get_self_cma_tcb(); tcb = ada_get_self_cma_tcb(); if( tcb == (tcb_t *) NULL || tcb->cma_tcb.exc_stack == (exc_context_t *) NULL ) { main_thread_cma_tcb.cma_tcb.exc_stack = &main_thread_cma_tcb.exc_stack; tcb = &main_thread_cma_tcb; } return ( &tcb->cma_tcb ); } static void tcb_io_allocate ( tcb_t *tcb ) { tcb->cma_tcb.select.rfds = (cma__t_file_mask *)cma__alloc_mem ( sizeof (cma__t_mask) * cma__g_nspm * 3); tcb->cma_tcb.select.wfds = (cma__t_file_mask *) ((int)tcb->cma_tcb.select.rfds + (sizeof (cma__t_mask) * cma__g_nspm)); tcb->cma_tcb.select.efds = (cma__t_file_mask *) ((int)tcb->cma_tcb.select.wfds + (sizeof (cma__t_mask) * cma__g_nspm)); if( tcb->cma_tcb.select.rfds == (cma__t_file_mask *) NULL || tcb->cma_tcb.select.wfds == (cma__t_file_mask *) NULL || tcb->cma_tcb.select.efds == (cma__t_file_mask *) NULL ) ada_thd_raise_exception( ADA_NO_MEMORY_E ); } void ada_thd_release_cma_tcb ( tcb_t *tcb ) { cma__free_mem( tcb->cma_tcb.select.rfds ); cma__free_mem( tcb->cma_tcb.select.wfds ); cma__free_mem( tcb->cma_tcb.select.efds ); free( tcb ); } #define INIT_THREAD_TCB( tcb, cv, mutex, lock, tkind ) \ { \ memset( (tcb), '\0', sizeof( tcb_t ) ); \ (tcb)->cma_tcb.kind = tkind; \ (tcb)->cma_tcb.exc_stack = &(tcb)->exc_stack; \ (char *) (tcb)->cma_tcb.tswait_cv = cv; \ (char *) (tcb)->cma_tcb.tswait_mutex = mutex; \ (char *) (tcb)->cma_tcb.mutex = lock; \ (tcb)->cma_tcb.alert.g_enable = 1; \ tcb_io_allocate( tcb ); \ } /**********************************************************************/ /* Creates a new CMA "pthread" TCB for the task and returns a pointer */ /* to the calling task. */ /**********************************************************************/ char *ada_thd_create_cma_thread_tcb ( char *cv, char *mutex, char *lock ) { tcb_t *tcb; tcb = (tcb_t *) malloc( sizeof( tcb_t ) ); if( tcb == (tcb_t *) NULL ) fputs( "Couldn't Allocate TCB\n", stderr ); INIT_THREAD_TCB( tcb, cv, mutex, lock, cma__c_thkind_normal ); return ( (char *) tcb ); } char *ada_thd_create_main_thread_tcb ( char *cv, char *mutex, char *lock ) { INIT_THREAD_TCB( &main_thread_cma_tcb, cv, mutex, lock, cma__c_thkind_normal ); return (( char *) &main_thread_cma_tcb ); } void ada_thd_thread_alert ( cma_t_thread *tcb ) { ( (tcb_t *) tcb)->cma_tcb.alert.pending = cma_c_true; }