STATUS CS_find_server_slot(i4 *slotno) { STATUS status = OK; CS_SERV_INFO *serv_info; i4 i; if (cs_servernum >= 0) { *slotno = cs_servernum; return(OK); } CS_getspin(&Cs_sm_cb->css_spinlock); serv_info = Cs_sm_cb->css_servinfo; /* find a free slot */ status = FAIL; for (i = 0; i < Cs_sm_cb->css_numservers; i++) { if (!serv_info[i].csi_in_use) { cs_servernum = *slotno = i; Cs_svinfo = &serv_info[i]; MEfill(sizeof (CS_SERV_INFO), '\0', (char *)Cs_svinfo); Cs_svinfo->csi_in_use = TRUE; Cs_svinfo->csi_id_number = i; /* Set this so we don't get any wakeup signals until cleared */ CS_TAS(&Cs_svinfo->csi_wakeme); i_EXsetothersig(SIGUSR2, SIG_IGN); Cs_svinfo->csi_pid = getpid(); Cs_svinfo->csi_signal_pid = Cs_svinfo->csi_pid; CS_SPININIT(&Cs_svinfo->csi_spinlock); status = OK; break; } } CS_relspin(&Cs_sm_cb->css_spinlock); return(status); }
/* ** Name: cpres_mbx_write_complete - QIO write completion handler. ** ** Description: ** This subroutine is called as a user-mode AST routine when the write I/O ** on the cross-process resume mailbox completes. ** ** It checks the IOSB for NOREADER and if true ** sets the channel status to CPchanDying. ** ** Inputs: ** cpid - *CS_CPID of writer containing ** iosb IOSB used for QIO ** data Pointer to CPchan ** ** Outputs: ** None ** ** Returns: ** void ** ** Side Effects: ** Channel may be taken out of service. ** ** History: ** 04-Apr-2008 (jonj) ** Created. */ static void cpres_mbx_write_complete( CS_CPID *cpid ) { CP_CHANNEL *CPchan; /* If reader has died, shutdown the channel */ if ( cpid->iosb.iosb$w_status == SS$_NOREADER ) { CPchan = (CP_CHANNEL*)cpid->data; /* Loop until we get the sem */ while ( !CS_TAS(&cpres_channels_sem) ); /* If not yet noticed, mark channel as dying */ if ( CPchan->state == CPchanIsAlive ) CPchan->state = CPchanIsDying; CS_ACLR(&cpres_channels_sem); } }
/* ** Name: cpres_mbx_assign - get channel to target process, assign if need ** ** Description: ** This subroutine looks up the channel to the target process. If we have ** not yet assigned a channel to the target process, then we assign one ** and remember it. The resulting channel is returned. ** ** Inputs: ** pid - the target process's pid ** ** Outputs: ** CPchan - Pointer to CP_CHANNEL of process. ** ** Returns: ** OK, !OK ** ** History: ** Summer, 1992 (bryanp) ** Working on the new portable logging and locking system. ** 14-dec-1992 (bryanp) ** ERsend() calls should be ERlog() calls. ** 23-may-1994 (bryanp) B60736 ** Added clean_channels() routine and called it periodically to ** ensure that a process doesn't accumulate channels to dead ** processes indefinitely. ** 02-May-2007 (jonj) ** Use of CSp/v_semaphore is prohibited from within an AST as ** it corrupts cs_inkernel and the ready queues. Use CS_ASET/ACLR ** instead. ** 08-Nov-2007 (jonj) ** Changed function to return pointer to CP_CHANNEL instead ** of channel number, initialize IsDead to FALSE. ** 04-Apr-2008 (jonj) ** Remove disabling of ASTs here, caller will have already done ** that. ** Check if PID has been deadified by write AST; if so, ** cancel any pending I/O, deassign channel, mark CPchan ** as unusuable (dead). */ static STATUS cpres_mbx_assign(PID pid, CP_CHANNEL **CPchan) { i4 i; struct dsc$descriptor_s name_desc; i4 vms_status; char mbx_name[100]; char *inst_id; char msg_buf[250]; STATUS status; STATUS cl_status; PID my_pid; CL_ERR_DESC local_sys_err; CP_CHANNEL *NewCPchan; /* Loop until we get the sem */ while ( !CS_TAS(&cpres_channels_sem) ); for (i = 0; i < cpres_num_channels_assigned; i++) { if (cpres_channels[i].pid == pid) { /* ** If write completion AST noticed that ** the reading process has died or gone away, ** mark its PID as dead, cancel any leftover ** I/O and deassign the channel. */ if ( cpres_channels[i].state == CPchanIsDying ) { sys$cancel(cpres_channels[i].chan); sys$dassgn(cpres_channels[i].chan); cpres_channels[i].state = CPchanIsDead; STprintf(msg_buf, "%x PID %x on channel %d is dead, deassigned", Cs_srv_block.cs_pid, cpres_channels[i].pid, cpres_channels[i].chan); ERlog(msg_buf, STlength(msg_buf), &local_sys_err); } /* Return channel, dead or alive */ *CPchan = &cpres_channels[i]; CS_ACLR(&cpres_channels_sem); return (OK); } } if ( status = clean_channels() ) { CS_ACLR(&cpres_channels_sem); return (status); } if ( cpres_num_channels_assigned < (sizeof(cpres_channels)/sizeof(CP_CHANNEL)) ) { /* ** New process, and room remains in the channel array, so assign a ** channel. */ NewCPchan = &cpres_channels[cpres_num_channels_assigned]; NMgtAt("II_INSTALLATION", &inst_id); if (inst_id && *inst_id) STprintf(mbx_name, "II_CPRES_%s_%x", inst_id, (i4)pid); else STprintf(mbx_name, "II_CPRES_%x", (i4)pid); name_desc.dsc$a_pointer = mbx_name; name_desc.dsc$w_length = STlength(mbx_name); name_desc.dsc$b_dtype = DSC$K_DTYPE_T; name_desc.dsc$b_class = DSC$K_CLASS_S; vms_status = sys$assign(&name_desc, /* devname */ &NewCPchan->chan, /* channel */ 0, /* access_mode */ 0, /* mbxnam */ AGN$M_WRITEONLY); /* flags */ if ( vms_status == SS$_NORMAL ) { NewCPchan->pid = pid; NewCPchan->state = CPchanIsAlive; *CPchan = NewCPchan; cpres_num_channels_assigned++; CS_ACLR(&cpres_channels_sem); return (OK); } else { STprintf(msg_buf, "%x cpres_mbx_assign: Error (%x) assigning channel to %s", Cs_srv_block.cs_pid, vms_status, mbx_name); ERlog(msg_buf, STlength(msg_buf), &local_sys_err); } } else { /* ** No room left in channels array. One possibility is to go through ** the array looking for assigned channels to mailboxes of dead ** processes and clean those up. */ STcopy("PANIC! No room left in channels array!", msg_buf); ERlog(msg_buf, STlength(msg_buf), &local_sys_err); } CS_ACLR(&cpres_channels_sem); return (FAIL); }