/* TCBUF.C - TCtask - Buffered Message handling routines. V1.1 T.Wagner V1.2 TECON Ltd. NOTE: None of the Buffer routines my be used from inside an interrupt handler. The routines are relatively slow, since they use the normal word pipe and resource calls. Optimization would be possible by using block moves and internally handling resources. */ #include #include "tsk.h" #include "tclocal.h" bufferptr create_buffer (bufferptr buf, nearptr pbuf, word bufsize #if (TSK_NAMEPAR) ,charptr name #endif ) { #if (TSK_DYNAMIC) if (buf == NULL) { if ((buf = tsk_alloc (sizeof (buffer))) == NULL) return NULL; buf->flags = F_TEMP; } else buf->flags = 0; if (pbuf == NULL) { if ((pbuf = tsk_alloc (bufsize)) == NULL) { if (buf->flags & F_TEMP) tsk_free (buf); return NULL; } buf->flags |= F_STTEMP; } #endif create_wpipe (&buf->pip, pbuf, bufsize #if (TSK_NAMEPAR) ,name #endif ); create_resource (&buf->buf_read #if (TSK_NAMEPAR) ,name #endif ); create_resource (&buf->buf_write #if (TSK_NAMEPAR) ,name #endif ); buf->msgcnt = 0; #if (TSK_NAMED) tsk_add_name (&buf->name, name, TYP_BUFFER, buf); #endif return buf; } void delete_buffer (bufferptr buf) { delete_wpipe (&buf->pip); delete_resource (&buf->buf_read); delete_resource (&buf->buf_write); buf->msgcnt = 0; #if (TSK_NAMED) tsk_del_name (&buf->name); #endif #if (TSK_DYNAMIC) if (buf->flags & F_STTEMP) tsk_free (buf->pip.wcontents); if (buf->flags & F_TEMP) tsk_free (buf); #endif } word_s read_buffer (bufferptr buf, nearptr msg, word_s size, dword timeout) { word_s i, len, l1, l2; word w; if ((i = request_resource (&buf->buf_read, timeout)) < 0) return i; if ((len = read_wpipe (&buf->pip, timeout)) < 0) { release_resource (&buf->buf_read); return len; } l1 = (len < size) ? len : size; for (i = 0; i < l1; i++) { if (!(i & 1)) w = read_wpipe (&buf->pip, 0L); else w = w >> 8; ((byteptr)msg) [i] = (byte)w; } l2 = (len + 1) >> 1; for (i = (l1 + 1) >> 1; i < l2; i++) read_wpipe (&buf->pip, 0L); if (l1 < size) ((byteptr)msg) [l1] = 0; buf->msgcnt--; release_resource (&buf->buf_read); return len; } word_s c_read_buffer (bufferptr buf, nearptr msg, word_s size) { word_s res; CRITICAL; res = -1; C_ENTER; if (buf->pip.filled && buf->buf_read.state) { request_resource (&buf->buf_read, 0L); C_LEAVE; res = read_buffer (buf, msg, size, 0L); } else C_LEAVE; return res; } local word_s near tsk_wrbuf (bufferptr buf, word w, dword timeout) { word_s i; if ((i = write_wpipe (&buf->pip, w, timeout)) < 0) release_resource (&buf->buf_write); return i; } word_s write_buffer (bufferptr buf, nearptr msg, word_s size, dword timeout) { word_s i, res, l2; if (size < 0 || (word)((size + 3) >> 1) > buf->pip.bufsize) return -3; if ((i = request_resource (&buf->buf_write, timeout)) < 0) return i; if ((i = tsk_wrbuf (buf, (word)size, timeout)) < 0) return i; l2 = (size + 1) >> 1; for (i = 0; i < l2; i++) if ((res = tsk_wrbuf (buf, ((wordptr)msg) [i], timeout)) < 0) return res; buf->msgcnt++; release_resource (&buf->buf_write); return size; } word_s c_write_buffer (bufferptr buf, nearptr msg, word_s size) { word_s res; CRITICAL; if (size < 0 || (word)((size + 3) >> 1) > buf->pip.bufsize) return -3; C_ENTER; res = -1; if (wpipe_free (&buf->pip) >= (word)((size + 3) >> 1) && buf->buf_write.state) { request_resource (&buf->buf_write, 0L); C_LEAVE; res = write_buffer (buf, msg, size, 0L); } else C_LEAVE; return res; } word check_buffer (bufferptr buf) { return buf->msgcnt; }