PRIVATE dce_pointer_t rpc__list_element_alloc ( rpc_list_desc_p_t list_desc, boolean32 block ) { volatile dce_pointer_t element = NULL; unsigned32 wait_cnt; struct timespec delta; struct timespec abstime; RPC_LOG_LIST_ELT_ALLOC_NTR; for (wait_cnt = 0; wait_cnt < rpc_g_lookaside_rcb.max_wait_times; wait_cnt++) { /* * Acquire the global resource control lock for all lookaside * lists if the caller doesn't have their own lock. */ if (list_desc->use_global_mutex) { RPC_MUTEX_LOCK (rpc_g_lookaside_rcb.res_lock); } /* * Try allocating a structure off the lookaside list given. */ if (list_desc->cur_size > 0) { #define DEBUG 1 #ifdef DEBUG if (list_desc->list_head.next == NULL) { /* * rpc_m_lookaside_corrupt * "(%s) Lookaside list is corrupted" */ rpc_dce_svc_printf ( __FILE__, __LINE__, "%s", rpc_svc_general, svc_c_sev_fatal | svc_c_action_abort, rpc_m_lookaside_corrupt, "rpc__list_element_alloc" ); } #endif list_desc->cur_size--; RPC_LIST_REMOVE_HEAD (list_desc->list_head, element, dce_pointer_t); /* * Release the global resource control lock for all lookaside * lists if the caller doesn't have their own lock. */ if (list_desc->use_global_mutex) { RPC_MUTEX_UNLOCK (rpc_g_lookaside_rcb.res_lock); } break; } else { /* * Release the global resource control lock if the * caller doesn't have their own lock for all lookaside lists * since the structure was available on the lookaside list. * * We do it now because allocating an element from heap is a relatively * time consuming operation. */ if (list_desc->use_global_mutex) { RPC_MUTEX_UNLOCK (rpc_g_lookaside_rcb.res_lock); } /* * The lookaside list is empty. Try and allocate from * heap. */ RPC_MEM_ALLOC (element, dce_pointer_t, list_desc->element_size, list_desc->element_type, RPC_C_MEM_NOWAIT); if (element == NULL) { /* * The heap allocate failed. If the caller indicated * that we should not block return right now. */ if (block == false) { break; } delta.tv_sec = rpc_g_lookaside_rcb.wait_time; delta.tv_nsec = 0; dcethread_get_expiration (&delta, &abstime); /* * If we are using the global lookaside list lock * then reaquire the global lookaside list lock and * wait on the global lookaside list condition * variable otherwise use the caller's mutex and * condition variable. */ if (list_desc->use_global_mutex) { RPC_MUTEX_LOCK (rpc_g_lookaside_rcb.res_lock); RPC_COND_TIMED_WAIT (rpc_g_lookaside_rcb.wait_flg, rpc_g_lookaside_rcb.res_lock, &abstime); RPC_MUTEX_UNLOCK (rpc_g_lookaside_rcb.res_lock); } else { RPC_COND_TIMED_WAIT (*list_desc->cond, *list_desc->mutex, &abstime); } /* * Try to allocate the structure again. */ continue; } else { /* * The RPC_MEM_ALLOC succeeded. If an alloc routine * was specified when the lookaside list was inited * call it now. */ if (list_desc->alloc_rtn != NULL) { /* * Catch any exceptions which may occur in the * list-specific alloc routine. Any exceptions * will be caught and the memory will be freed. */ DCETHREAD_TRY { (*list_desc->alloc_rtn) (element); } DCETHREAD_CATCH_ALL(THIS_CATCH) { RPC_MEM_FREE (element, list_desc->element_type); element = NULL; /* * rpc_m_call_failed_no_status * "%s failed" */ rpc_dce_svc_printf ( __FILE__, __LINE__, "%s", rpc_svc_general, svc_c_sev_fatal | svc_c_action_abort, rpc_m_call_failed_no_status, "rpc__list_element_alloc/(*list_desc->alloc_rtn)(element)" ); } DCETHREAD_ENDTRY } break; } } }
INTERNAL void network_monitor_liveness(void) { rpc_dg_client_rep_p_t client; unsigned32 i; struct timespec next_ts; RPC_DBG_PRINTF(rpc_e_dbg_conv_thread, 1, ("(network_monitor_liveness) starting up...\n")); RPC_MUTEX_LOCK(monitor_mutex); while (stop_monitor == false) { /* * Awake every 60 seconds. */ rpc__clock_timespec(rpc__clock_stamp()+60, &next_ts); RPC_COND_TIMED_WAIT(monitor_cond, monitor_mutex, &next_ts); if (stop_monitor == true) break; for (i = 0; i < CLIENT_TABLE_SIZE; i++) { client = client_table[i]; while (client != NULL && active_monitors != 0) { if (client->rundown != NULL && rpc__clock_aged(client->last_update, RPC_CLOCK_SEC(LIVE_TIMEOUT_INTERVAL))) { /* * If the timer has expired, call the rundown routine. * Stop monitoring the client handle by setting its rundown * routine pointer to NULL. */ RPC_DBG_PRINTF(rpc_e_dbg_general, 3, ("(network_monitor_liveness_timer) Calling rundown function\n")); RPC_MUTEX_UNLOCK(monitor_mutex); (*client->rundown)((rpc_client_handle_t)client); RPC_MUTEX_LOCK(monitor_mutex); /* * The monitor is no longer active. */ client->rundown = NULL; active_monitors--; } client = client->next; } if (active_monitors == 0) { /* * While we were executing the rundown function and opened the * mutex, the fork handler might try to stop us. */ if (stop_monitor == true) break; /* * Nothing left to monitor, so terminate the thread. */ dcethread_detach_throw(monitor_task); monitor_running = false; RPC_DBG_PRINTF(rpc_e_dbg_conv_thread, 1, ("(network_monitor_liveness) shutting down (no active)...\n")); RPC_MUTEX_UNLOCK(monitor_mutex); return; } } } RPC_DBG_PRINTF(rpc_e_dbg_conv_thread, 1, ("(network_monitor_liveness) shutting down...\n")); RPC_MUTEX_UNLOCK(monitor_mutex); }