/*------------------------------------------------------------------------
 *  semreset  -  Reset a semaphore's count and release waiting processes
 *------------------------------------------------------------------------
 */
syscall	semreset(
    sid32		sem,		/* ID of semaphore to reset	*/
    int32		count		/* New count (must be >= 0)	*/
)
{
    intmask	mask;			/* Saved interrupt mask		*/
    struct	sentry *semptr;		/* Ptr to semaphore table entry */
    qid16	semqueue;		/* Semaphore's process queue ID	*/
    pid32	pid;			/* ID of a waiting process	*/

    mask = disable();

    if (count < 0 || isbadsem(sem) || semtab[sem].sstate==S_FREE) {
        restore(mask);
        return SYSERR;
    }

    semptr = &semtab[sem];
    semqueue = semptr->squeue;	/* Free any waiting processes */
    resched_cntl(DEFER_START);
    while ((pid=getfirst(semqueue)) != EMPTY)
        ready(pid);
    semptr->scount = count;		/* Reset count as specified */
    resched_cntl(DEFER_STOP);
    restore(mask);
    return OK;
}
Exemple #2
0
/*------------------------------------------------------------------------
 *  alarmwakeup  -  Called by clock interrupt handler to awaken processes to call alarm handler
 *------------------------------------------------------------------------
 */
void	alarmwakeup(void)
{
	/* LAB 4Q3 Awaken all processes that have no more time to sleep */
	resched_cntl(DEFER_START);
	while (alarmnonempty(alarmq) && (alarmfirstkey(alarmq) <= 0)) {
		pid32 timeoutProcess = alarmdequeue(alarmq);
		//  LAB 4Q3 If current process then just invoke the callback function
		if (timeoutProcess == currpid) {

			struct procent *prptr = &proctab[currpid];
			void (*alarmFunction) () = prptr->alarmfunc;
			prptr->alarmtime = 0;
			prptr->alarmTimeOut = FALSE;
			alarmFunction();
			prptr->alarmfunc = NULL;

		} else {

			//  LAB 4Q3 if not the current process then ready the process frocibly in order to run the
			// alarm callback function context switch in.
			struct procent *prptr = &proctab[timeoutProcess];
			prptr->alarmTimeOut = TRUE;
			if (prptr->prstate == PR_SLEEP) {
				unsleep(timeoutProcess);
				ready(timeoutProcess);
			}
		}
	}

	resched_cntl(DEFER_STOP);
	return;
}
/*------------------------------------------------------------------------
 * udp_release  -  Release a previously-registered UDP slot
 *------------------------------------------------------------------------
 */
status	udp_release (
	 uid32	slot			/* Table slot to release	*/
	)
{
	intmask	mask;			/* Saved interrupt mask		*/
	struct	udpentry *udptr;	/* Pointer to udptab entry	*/
	struct	netpacket *pkt;		/* pointer to packet being read	*/

	/* Ensure only one process can access the UDP table at a time	*/

	mask = disable();

	/* Verify that the slot is valid */

	if ( (slot < 0) || (slot >= UDP_SLOTS) ) {
		restore(mask);
		return SYSERR;
	}

	/* Get pointer to table entry */

	udptr = &udptab[slot];

	/* Verify that the slot has been registered and is valid */

	if (udptr->udstate == UDP_FREE) {
		restore(mask);
		return SYSERR;
	}

	/* Defer rescheduling to prevent freebuf from switching context	*/

	resched_cntl(DEFER_START);
	while (udptr->udcount > 0) {
		pkt = udptr->udqueue[udptr->udhead++];
		if (udptr->udhead >= UDP_QSIZ) {
			udptr->udhead = 0;
		}
		freebuf((char *)pkt);
		udptr->udcount--;
	}
	udptr->udstate = UDP_FREE;
	resched_cntl(DEFER_STOP);
	restore(mask);
	return OK;
}
/*------------------------------------------------------------------------
 * icmp_release  -  Release a previously-registered ICMP icmpid
 *------------------------------------------------------------------------
 */
status	icmp_release (
	 int32	icmpid			/* Slot in icmptab to release	*/
	)
{
	intmask	mask;			/* Saved interrupt mask		*/
	struct	icmpentry *icmptr;	/* Pointer to icmptab entry	*/
	struct	netpacket *pkt;		/* Pointer to packet		*/

	mask = disable();

	/* Check arg and insure entry in table is in use */

	if ( (icmpid < 0) || (icmpid >= ICMP_SLOTS) ) {
		restore(mask);
		return SYSERR;
	}
	icmptr = &icmptab[icmpid];
	if (icmptr->icstate != ICMP_USED) {
		restore(mask);
		return SYSERR;
	}

	/* Remove each packet from the queue and free the buffer */

	resched_cntl(DEFER_START);
	while (icmptr->iccount > 0) {
		pkt = icmptr->icqueue[icmptr->ichead++];
		if (icmptr->ichead >= ICMP_SLOTS) {
			icmptr->ichead = 0;

		}
		freebuf((char *)pkt);
		icmptr->iccount--;
	}

	/* Mark the entry free */

	icmptr->icstate = ICMP_FREE;
	resched_cntl(DEFER_STOP);
	restore(mask);
	return OK;
}
/*------------------------------------------------------------------------
 *  ttyhandler - Handle an interrupt for a tty (serial) device
 *------------------------------------------------------------------------
 */
void ttyhandler(uint32 xnum) {
	struct	dentry	*devptr;	/* Address of device control blk*/
	struct	ttycblk	*typtr;		/* Pointer to ttytab entry	*/	
	struct	uart_csreg *csrptr;	/* Address of UART's CSR	*/
	uint32	iir = 0;		/* Interrupt identification	*/
	uint32	lsr = 0;		/* Line status			*/

	/* Get CSR address of the device (assume console for now) */

	devptr = (struct dentry *) &devtab[CONSOLE];

	csrptr = (struct uart_csreg *) devptr->dvcsr;

	/* Obtain a pointer to the tty control block */

	typtr = &ttytab[ devptr->dvminor ];

	/* Decode hardware interrupt request from UART device */

        /* Check interrupt identification register */
        iir = csrptr->iir;

        if (iir & UART_IIR_IRQ) {
		return;
        }

	/* Decode the interrupt cause based upon the value extracted	*/
	/* from the UART interrupt identification register.  Clear	*/
	/* the interrupt source and perform the appropriate handling	*/
	/* to coordinate with the upper half of the driver		*/

        /* Decode the interrupt cause */

	iir &= UART_IIR_IDMASK;		/* Mask off the interrupt ID */
        switch (iir) {

	    /* Receiver line status interrupt (error) */

	    case UART_IIR_RLSI:
		lsr = csrptr->lsr;
		if(lsr & UART_LSR_BI) { /* Break Interrupt */
			lsr = csrptr->buffer; /* Read the RHR register to acknowledge */
		}
		return;

	    /* Receiver data available or timed out */

	    case UART_IIR_RDA:
	    case UART_IIR_RTO:

		resched_cntl(DEFER_START);

		/* While chars avail. in UART buffer, call ttyhandle_in	*/

		while ( (csrptr->lsr & UART_LSR_DR) != 0) {
			ttyhandle_in(typtr, csrptr);
                }

		resched_cntl(DEFER_STOP);

		return;

            /* Transmitter output FIFO is empty (i.e., ready for more)	*/

	    case UART_IIR_THRE:

		ttyhandle_out(typtr, csrptr);
		return;

	    /* Modem status change (simply ignore) */

	    case UART_IIR_MSC:
		return;
	    }
}