Beispiel #1
0
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);
}
Beispiel #2
0
/*
** 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);
    }
}
Beispiel #3
0
/*
** 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);
}