/* TCPIP.C - TCtask - Pipe handling routines. V1.1 T.Wagner V1.2 TECON Ltd. */ #include #include "tsk.h" #include "tclocal.h" /* create_pipe - initialises pipe. */ pipeptr create_pipe (pipeptr pip, nearptr buf, word bufsize #if (TSK_NAMEPAR) ,charptr name #endif ) { #if (TSK_DYNAMIC) if (pip == NULL) { if ((pip = tsk_alloc (sizeof (pipe))) == NULL) return NULL; pip->flags = F_TEMP; } else pip->flags = 0; if (buf == NULL) { if ((buf = tsk_alloc (bufsize)) == NULL) { if (pip->flags & F_TEMP) tsk_free (pip); return NULL; } pip->flags |= F_STTEMP; } #endif pip->wait_read = pip->wait_write = pip->wait_clear = NULL; pip->outptr = pip->inptr = pip->filled = 0; pip->bufsize = bufsize; pip->contents = (byteptr)buf; #if (TSK_NAMED) tsk_add_name (&pip->name, name, TYP_PIPE, pip); #endif return pip; } /*-------------------------------------------------------------------*/ /* delete_pipe - kills all processes waiting for reading from or writing to the pipe. */ void delete_pipe (pipeptr pip) { CRITICAL; C_ENTER; tsk_kill_queue (&(pip->wait_read)); tsk_kill_queue (&(pip->wait_write)); tsk_kill_queue (&(pip->wait_clear)); pip->outptr = pip->inptr = pip->filled = 0; C_LEAVE; #if (TSK_NAMED) tsk_del_name (&pip->name); #endif #if (TSK_DYNAMIC) if (pip->flags & F_STTEMP) tsk_free (pip->contents); if (pip->flags & F_TEMP) tsk_free (pip); #endif } /*-------------------------------------------------------------------*/ /* read_pipe - Wait until a character is written to the pipe. If there is a character in the pipe on entry, it is assigned to the caller, and the task continues to run. If there are tasks waiting to write, the first task is made eligible, and the character is inserted into the pipe. */ word_s read_pipe (pipeptr pip, dword timeout) { tcbptr curr; word_s res; CRITICAL; C_ENTER; if (pip->filled) { res = pip->contents [pip->outptr++]; if (pip->outptr >= pip->bufsize) pip->outptr = 0; pip->filled--; if ((curr = pip->wait_write) != NULL) { pip->contents [pip->inptr++] = (byte)curr->retsize; if (pip->inptr >= pip->bufsize) pip->inptr = 0; pip->filled++; pip->wait_write = tsk_runable (curr); curr->retptr = NULL; } else if (!pip->filled) while (pip->wait_clear != NULL) pip->wait_clear = tsk_runable (pip->wait_clear); C_LEAVE; return res; } tsk_current->state = ST_WAITING; tsk_current->queue = (tqueptr)&pip->wait_read; tsk_enqtimer (tsk_current, timeout); schedule (); return (word_s)tsk_current->retptr; } /*-------------------------------------------------------------------*/ /* c_read_pipe - If there is a character in the pipe on entry, read_pipe is called, otherwise en error status is returned. */ word_s c_read_pipe (pipeptr pip) { CRITICAL, res; C_ENTER; res = (pip->filled) ? read_pipe (pip, 0L) : -1; C_LEAVE; return res; } /*-------------------------------------------------------------------*/ /* write_pipe - Wait until space for the character to be written to the pipe is available. If there is enough space in the pipe on entry, the character is inserted into the pipe, and the task continues to run. If there are tasks waiting to read, the first task is made eligible, and the character is passed to the waiting task. */ word_s write_pipe (pipeptr pip, byte ch, dword timeout) { tcbptr curr; CRITICAL; C_ENTER; if (pip->filled < pip->bufsize) { pip->contents [pip->inptr++] = ch; if (pip->inptr >= pip->bufsize) pip->inptr = 0; pip->filled++; if ((curr = pip->wait_read) != NULL) { pip->wait_read = tsk_runable (curr); curr->retptr = (nearptr)pip->contents [pip->outptr++]; if (pip->outptr >= pip->bufsize) pip->outptr = 0; pip->filled--; } C_LEAVE; return 0; } tsk_current->retsize = ch; tsk_current->state = ST_WAITING; tsk_current->queue = (tqueptr)&pip->wait_write; tsk_enqtimer (tsk_current, timeout); schedule (); return (word_s)tsk_current->retptr; } /*-------------------------------------------------------------------*/ /* c_write_pipe - If there is space for the character in the pipe on entry, write_pipe is called, otherwise en error status is returned. */ word_s c_write_pipe (pipeptr pip, byte ch) { word_s res; CRITICAL; C_ENTER; res = (pip->filled < pip->bufsize) ? write_pipe (pip, ch, 0L) : -1; C_LEAVE; return res; } /*-------------------------------------------------------------------*/ /* wait_pipe_empty - Wait until the pipe is empty. If the pipe is empty on entry, the task continues to run. */ word_s wait_pipe_empty (pipeptr pip, dword timeout) { CRITICAL; C_ENTER; if (!pip->filled) { C_LEAVE; return 0; } tsk_current->retptr = NULL; tsk_wait (&pip->wait_clear, timeout); return (word_s)tsk_current->retptr; } /*-------------------------------------------------------------------*/ /* check_pipe - returns -1 if there are no characters in the pipe, else the first available character. */ word_s check_pipe (pipeptr pip) { return (pip->filled) ? (word_s)pip->contents [pip->outptr] : -1; } /*-------------------------------------------------------------------*/ /* pipe_free - returns the number of free characters in the pipe. */ word pipe_free (pipeptr pip) { return pip->bufsize - pip->filled; } /*-------------------------------------------------------------------*/